Symfony 7:如何让公开路由跳过提前触发的access_token.token_handler?
Symfony 7 中让公开路由跳过 AccessTokenHandler 验证的方案
问题背景
使用AccessTokenHandler处理令牌验证,但PUBLIC_ACCESS标记的路由(示例中为/auth前缀)无需验证。但Symfony的access_token处理器会在access_control规则之前触发,导致公开路由也会执行令牌验证逻辑,需要解决这一冲突。
最优解决方案:拆分防火墙
这是最符合Symfony安全组件设计逻辑的方案,将公开路由与需要验证的路由分配到不同防火墙,让公开路由的防火墙完全跳过安全验证流程。
修改security.yaml配置如下:
# security.yaml firewalls: # 公开路由专用防火墙,关闭安全验证 public: pattern: ^/auth security: false # 需令牌验证的主防火墙 main: pattern: ^/ json_login: check_path: sign_in username_path: email password_path: password access_token: token_handler: App\Security\AccessTokenHandler access_control: - { path: ^/auth, roles: PUBLIC_ACCESS } - { path: ^/*, roles: ROLE_USER }
security: false会让/auth前缀的路由完全跳过所有安全验证步骤,自然不会触发AccessTokenHandler- 主防火墙
main匹配其余所有路由,正常执行令牌验证逻辑
备选方案:在AccessTokenHandler中判断请求路径
如果无法拆分防火墙,可以在处理器中注入RequestStack,判断当前请求是否属于公开路由,若是则直接返回匿名用户徽章以跳过令牌验证。
修改AccessTokenHandler.php代码如下:
# AccessTokenHandler.php use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\Security\Core\User\AnonymousUser; readonly class AccessTokenHandler implements AccessTokenHandlerInterface { public function __construct( private ApiTokenRepository $repository, private RequestStack $requestStack ) { } public function getUserBadgeFrom(string $accessToken): UserBadge { $request = $this->requestStack->getCurrentRequest(); // 匹配公开路由前缀 if ($request && str_starts_with($request->getPathInfo(), '/auth')) { // 返回匿名用户徽章,跳过令牌验证 return new UserBadge('anon.', fn() => new AnonymousUser()); } $accessTokenEntity = $this->repository->findOneByValue($accessToken); if (is_null($accessTokenEntity) || !$accessTokenEntity->isValid()) { throw new BadCredentialsException('Invalid credentials.'); } return new UserBadge($accessTokenEntity->getUser()->getUserIdentifier()); } }
- 该方案通过在处理器内部判断路由实现需求,但逻辑耦合度更高,仅适合无法拆分防火墙的场景
内容的提问来源于stack exchange,提问作者Oleg Vartanov
相关产品推荐
相关产品推荐

