Spring Security访问不存在的/api端点返回403而非404的问题
访问不存在的/api端点返回403而非404的原因及解决方法
核心原因
问题出在过滤器执行顺序和你自定义的ResourceOwnershipFilter逻辑上:
- Spring Security的过滤器链执行优先级高于Spring MVC的DispatcherServlet。当请求
/api/v1/doesnotexists时,会先进入Security过滤器链,而非直接由DispatcherServlet判断端点是否存在。 - 你的Security配置中,
/api/**路径要求已认证,而你确认请求已通过认证,这一步是放行的。但后续执行的ResourceOwnershipFilter(在UsernamePasswordAuthenticationFilter之前添加)会对所有/api/**请求做资源所有权验证——当目标端点不存在时,过滤器可能因无法找到对应资源的权限配置,直接返回403拒绝访问,此时请求还未到达DispatcherServlet,自然不会触发404逻辑。
解决方法
方法一:让过滤器仅对存在的/api端点做验证
修改ResourceOwnershipFilter,先判断请求是否对应已定义的控制器端点,不存在则直接放行到DispatcherServlet(会返回404):
@Component public class ResourceOwnershipFilter extends OncePerRequestFilter { @Autowired private RequestMappingHandlerMapping handlerMapping; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { // 检查当前请求是否有对应的控制器处理方法 try { handlerMapping.getHandler(request); } catch (NoHandlerFoundException e) { // 无匹配端点,放行到DispatcherServlet返回404 filterChain.doFilter(request, response); return; } // 存在匹配端点,执行你的资源所有权验证逻辑 // ...此处编写原有的权限校验代码 filterChain.doFilter(request, response); } }
方法二:调整过滤器执行顺序(不推荐)
将Security过滤器链的执行顺序调整到DispatcherServlet之后,让Spring MVC先判断端点是否存在,再执行Security校验。但这种方式会绕过Security对不存在/api/**端点的保护,仅在特殊场景下考虑使用。
内容的提问来源于stack exchange,提问作者whatspoppin
相关产品推荐
相关产品推荐

