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

发布于 2024-12-10 04:23:49 字数 754 浏览 0 评论 0原文

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

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

我能想到的处理此问题的最佳方法是创建一个自定义侦听器,用于侦听 kernel.request 事件并检查两件事:

  • 检查请求方法是否为 POST
  • 检查用户是否完全同意 。

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

但我的侦听器(预期)会针对所有请求触发 - 我想将其限制为仅检查请求是否针对受防火墙保护的 URL。是否可以通过编程方式检查这一点?

我也有一个挥之不去的怀疑,有一种更简单的方法可以解决这个问题,但无法弄清楚,所以如果有人有任何提示,我很想听听他们:)

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

现在,如果我尚未登录并向 api/get/something (位于防火墙后面)发出 POST 请求,Symfony 将返回描述登录页面的 HTML。相反,我只想回显类似 {error: 'User is notauthored'} 的内容。但我只希望这种情况发生在 POST 请求上。

I have a situation where I need to run some code if the user tries accessing a protected URL and is not authenticated / authorized.

By default, Symfony handles unauthenticated users by redirecting or forwarding the user to a login form. I'd like to prevent this from happening if the request method is POST, and instead echo a JSON object.

The best way I can think of to handle this is to create a custom listener that listens to the kernel.request event and checks two things:

  • checks if the request method is POST
  • checks if the user is fully
    authenticated

If it is a POST request, and the user is not fully authenticated, I would echo a JSON object.

But my listener is (expectedly) firing for all requests - I'd like to limit it to only check if the request is for a URL protected by the firewall. Is it possible to check this programatically?

I also have a nagging suspicion there's a simpler way to go about this, but can't figure it out, so if anyone has any tips, I'd love to hear them :)

Edit
@Problematic - The reason for checking only firewalled requests is because I have some requests that aren't firewalled, and if my code is fired, I'll receive the aforementioned JSON object instead of the request's real response.

Right now if I'm not logged in and make a POST request to api/get/something (which is behind the firewall), Symfony returns the HTML describing the login page. Instead, I want to just echo something like {error: 'User is not authorized'}. But I only want this to happen for POST requests.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

凌乱心跳 2024-12-17 04:23:49

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

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

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

由于启动身份验证过程是我想要避免的,因此我编写了自己的事件侦听器,该事件侦听器在 Symfony 的 ExceptionListener 之前拦截 kernel.exception做。我给我的事件监听器的优先级为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);
            }
        }
    }

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

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

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

I think I was going about this the wrong way. I wanted to know if a URL was behind the firewall, but I think I should've been trying to find out if the current user was authorized for the request. In essense, knowing that a user is denied access to a URL means that the URL must be behind a firewall, otherwise access couldn't have been denied.

Keeping this in mind, I was able to get the end result I wanted. It's pretty simple once you realize how the security mechanism works...

  • Symfony\Component\Security\Http\Firewall listens for the
    kernel.request event
  • Firewall then calls a number of event listeners that are registered in security.yml
  • If any security violation (i.e. a user trying to access something without being logged in) is detected, an AccessDeniedException is thrown, and the kernel.exception event is dispatched.
  • Symfony/Component/Security/Http/Firewall/ExceptionListener listens for the event and fires its onKernelException method which decides what the next step is. In my case, it would start the Authentication process

Since starting the Authentication process is what I wanted to avoid, I wrote my own event listener that intercepts kernel.exception before Symfony's ExceptionListener does. I gave my event listener a priority of 1.

This is the method I wrote:

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);
            }
        }
    }

As long as the user isn't authorized, and the request method is POST, a JSON object is returned (which also stops the event propogation) instead of the HTML for the login page. Otherwise, other listeners of kernel.exception will react and Symfony can go about its business.

So, the original question remains unanswered, but I think it could be accomplished by checking if a user has access to an action. Symfony\Component\Security\Core\Authorization\AccessDecisionManager looks like it'd be helpful for this.

Edit
I don't know if this method only handles users that aren't logged in. I haven't tested it yet, but I think it will also fire if a (logged in) user tries accessing an action that requires a role they haven't been granted. If this causes a problem, I would try modifying it to use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolver's isFullFledged($token) method to only care about users who aren't logged in.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文