是否可以以编程方式查看防火墙后面的URL /路由是否受到保护?

Ste*_*nte 6 firewall symfony

我有一种情况,如果用户尝试访问受保护的URL并且未经过身份验证/授权,我需要运行一些代码.

默认情况下,Symfony通过将用户重定向或转发到登录表单来处理未经身份验证的用户.如果请求方法是POST,我想阻止这种情况发生,而是回显JSON对象.

我能想到的最好的方法是创建一个自定义侦听器来侦听kernel.request事件并检查两件事:

  • 检查请求方法是否为POST
  • 检查用户是否完全通过身份验证

如果它是POST请求,并且用户未完全通过身份验证,我将回显JSON对象.

但我的听众(预期)会针对所有请求进行解雇 - 我想将其限制为仅检查请求是否针对受防火墙保护的URL.有可能以编程方式检查这个吗?

我也有一种唠叨的怀疑,有一种更简单的方法可以解决这个问题,但无法弄明白,所以如果有人有任何提示,我很乐意听到他们:)

编辑
@Problematic - 仅检查防火墙请求的原因是因为我有一些没有防火墙的请求,如果我的代码被触发,我将收到上述JSON对象而不是请求的真实响应.

现在,如果我没有登录并发出POST请求api/get/something(位于防火墙后面),Symfony将返回描述登录页面的HTML.相反,我想回应一些类似的东西{error: 'User is not authorized'}.但我只希望这发生在POST请求中.

Ste*_*nte 3

我想我的处理方式是错误的。我想知道某个 URL 是否位于防火墙后面,但我认为我应该尝试查明当前用户是否已获得该请求的授权。从本质上讲,知道用户被拒绝访问某个 URL 意味着该 URL 必须位于防火墙后面,否则访问不可能被拒绝。

记住这一点,我能够得到我想要的最终结果。一旦您了解安全机制的工作原理,事情就变得非常简单......

  • Symfony\Component\Security\Http\Firewall监听 kernel.request事件
  • 然后防火墙调用一些注册的事件监听器security.yml
  • 如果检测到任何安全违规(即用户尝试在未登录的情况下访问某些内容),则会AccessDeniedException抛出 并kernel.exception调度该事件。
  • Symfony/Component/Security/Http/Firewall/ExceptionListener监听事件并触发其onKernelException方法来决定下一步是什么。就我而言,它将启动身份验证过程

由于启动身份验证过程是我想要避免的,因此我编写了自己的事件监听器,kernel.exception在 Symfony 之前ExceptionListener进行拦截。我给事件侦听器的优先级为 1。

这是我写的方法:

public function handleException(GetResponseForExceptionEvent $event) {
        $exception = $event->getException();
        $request = $event->getRequest();
        if ($request->getMethod() == 'POST') {
            if ($exception instanceof AccessDeniedException) {
                $response = new Response({err: 'not logged in'});
                $event->setResponse($response);
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

只要用户未经授权,并且请求方法为 POST,就会返回一个 JSON 对象(这也会停止事件传播)而不是登录页面的 HTML。否则,其他听众kernel.exception将会做出反应,而 Symfony 可以继续其业务。

因此,最初的问题仍然没有得到解答,但我认为可以通过检查用户是否有权访问某个操作来完成。Symfony\Component\Security\Core\Authorization\AccessDecisionManager看起来这对此会有帮助。

编辑
我不知道这个方法是否处理未登录的用户。我还没有测试它,但我认为如果(已登录)用户尝试访问需要他们的角色的操作,它也会触发尚未被授予。如果这导致问题,我会尝试将其修改为使用 的Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolver方法 isFullFledged($token)来仅关心未登录的用户。