Error 403与Error 404问题:普通用户访问/settings返回404而非403
问题分析与解决方案
嘿,这个场景我碰到过!管理员能正常访问/settings说明你的权限规则和页面映射本身是没问题的,普通用户返回404而非403,大概率是权限被拒绝后的错误处理逻辑出了问题,导致系统试图跳转到一个不存在的页面,最终返回404。下面是具体的排查和解决步骤:
可能的原因
- 自定义错误页路径不存在:如果你的配置里加了
.accessDeniedPage("/403"),但没给/403路径配对应的控制器或静态页面,普通用户被拒后会跳转到这个不存在的地址,直接返回404。 - 默认错误处理失效:没配自定义权限拒绝处理器的话,Spring Security默认会重定向到
/error路径,但如果你的应用自定义了ErrorController却没处理好403场景,或者删掉了Spring Boot默认的错误页,也会导致404。 - 路径尾部斜杠不兼容:如果普通用户访问的是
/settings/(带尾部斜杠),而你的antMatchers("/settings")没匹配这个路径,同时Spring MVC的useTrailingSlashMatch被改成了false(默认是true),请求就找不到对应的控制器,返回404。
解决方案
1. 配置明确的权限拒绝处理器
直接在HttpSecurity配置里加自定义的accessDeniedHandler,强制返回403状态码,避免跳转到不存在的页面:
@Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/settings").hasAuthority("Administrator") .anyRequest().authenticated() .and() .formLogin() .loginPage("/login").permitAll() // 这里补全你的登录相关配置 .and() // 添加权限拒绝处理逻辑 .exceptionHandling() .accessDeniedHandler((request, response, accessDeniedException) -> { response.setStatus(HttpServletResponse.SC_FORBIDDEN); // 如果是后端页面,转发到自定义403页面 // request.getRequestDispatcher("/403").forward(request, response); // 如果是前后端分离,返回JSON错误信息 response.setContentType("application/json;charset=UTF-8"); response.getWriter().write("{\"code\":403,\"msg\":\"您没有访问该页面的权限\"}"); }); }
2. 修复自定义错误页配置
如果你确实需要跳转到自定义403页面,确保/403路径有对应的资源:
- 静态页面:在
src/main/resources/static/或src/main/resources/templates/下创建403.html(或对应模板引擎的文件,比如Thymeleaf的403.html)。 - 控制器映射:添加一个简单的控制器方法处理
/403请求:
@GetMapping("/403") public String showAccessDeniedPage() { return "403"; // 对应模板文件的名称 }
3. 统一路径匹配规则
如果是尾部斜杠的问题,有两种解决方式:
- 扩展Ant匹配规则:把
antMatchers("/settings")改成antMatchers("/settings", "/settings/"),同时匹配带和不带斜杠的路径。 - 开启Spring MVC尾部斜杠匹配(如果之前被修改过):
@Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void configurePathMatch(PathMatchConfigurer configurer) { configurer.setUseTrailingSlashMatch(true); // 默认就是true,除非你之前手动关了 } }
内容的提问来源于stack exchange,提问作者user9729328
相关产品推荐
相关产品推荐

