Silex多防火墙配置问题:已登录状态下API请求仍被重定向
解决方案:调整Silex安全配置以适配API与Admin的认证需求
先拆解你遇到的核心问题:
- 已登录的/admin会话无法被/api/v1端点识别,因为防火墙是独立配置的,没有共享会话认证逻辑
- 未认证访问/api/v1非开放端点时返回302重定向,不符合API场景的预期
下面是具体的配置调整方案:
1. 修正防火墙配置,共享Admin会话并开放指定API端点
修改security.firewalls配置,让需要认证的/api/v1端点复用/admin的会话认证,同时明确开放两个特定端点:
[ // 优先匹配开放的API端点,允许匿名访问 'api_v1_open' => [ 'pattern' => '^/api/v1/(details|failures)', 'anonymous' => true, ], // Admin后台的认证防火墙 'secured' => [ 'pattern' => '^/admin', 'http' => false, 'form' => [ 'login_path' => '/login', 'check_path' => '/admin/login_check', 'default_target_path' => '/admin' ], 'logout' => [ 'logout_path' => '/admin/logout', 'invalidate_session' => true, 'target_url' => '/login' ], 'users' => new UserProvider, ], // 需要认证的API端点,复用Admin的会话 'api_v1_secured' => [ 'pattern' => '^/api/v1', 'anonymous' => false, 'stateless' => false, // 保持会话状态,复用Admin的登录会话 'users' => new UserProvider, // 和Admin使用同一个用户提供者 // 针对API请求,禁用表单登录重定向,改用自定义401响应 'entry_point' => function () { $response = new \Symfony\Component\HttpFoundation\JsonResponse( ['error' => 'Unauthorized'], \Symfony\Component\HttpFoundation\Response::HTTP_UNAUTHORIZED ); return $response; }, ], ];
2. 调整访问控制规则,明确API权限
修改security.access_rules,区分开放和需要认证的API:
[ ['^/admin', 'ROLE_ADMIN'], ['^/api/v1/(details|failures)', 'IS_AUTHENTICATED_ANONYMOUSLY'], // 允许匿名访问开放端点 ['^/api/v1', 'ROLE_ADMIN'], // 其他API需要管理员权限 ]
3. 处理AJAX请求的重定向问题(关键)
默认情况下,未认证请求访问权限端点时会重定向到登录页,对于AJAX请求我们需要拦截这个行为,返回401 JSON响应。你可以通过添加自定义安全监听器实现:
// 在Silex应用中注册监听器 $app->on('security.authentication.failure', function ($event) use ($app) { $request = $event->getRequest(); if ($request->isXmlHttpRequest()) { $response = new \Symfony\Component\HttpFoundation\JsonResponse( ['error' => 'Authentication failed'], \Symfony\Component\HttpFoundation\Response::HTTP_UNAUTHORIZED ); $event->setResponse($response); } }); $app->on('security.access.denied', function ($event) use ($app) { $request = $event->getRequest(); if ($request->isXmlHttpRequest()) { $response = new \Symfony\Component\HttpFoundation\JsonResponse( ['error' => 'Access denied'], \Symfony\Component\HttpFoundation\Response::HTTP_FORBIDDEN ); $event->setResponse($response); } });
配置说明
- 防火墙顺序:Silex按配置顺序匹配防火墙,所以开放API的防火墙要放在最前面,优先匹配后不会进入后续认证防火墙
- 会话共享:
api_v1_secured防火墙设置stateless: false并复用Admin的UserProvider,确保已登录的/admin会话Cookie能被/api/v1端点识别 - API入口点:自定义
entry_point确保未认证的API请求返回401 JSON,而非重定向到登录页 - AJAX监听器:拦截认证失败和访问被拒绝事件,针对AJAX请求返回JSON响应,避免前端收到302重定向
这样配置后就能实现你的需求:
- 登录/admin后,发起的/api/v1/*请求会自动携带会话Cookie完成认证
- 未认证时,仅/api/v1/details和/api/v1/failures可正常访问,其他/api/v1端点返回401 JSON响应
内容的提问来源于stack exchange,提问作者Andrew Plank
相关产品推荐
相关产品推荐

