Spring Security资源访问权限配置问题及404错误排查咨询
兄弟,我太懂这种被Spring Security配置绕晕的感觉了!花5小时确实够折磨的,我来给你拆解清楚这三个配置的作用,再帮你定位404的问题。
先逐个理清楚你的三个配置到底在干嘛
1. SecurityConfiguration里的configure(HttpSecurity)
这是Spring Security的核心HTTP权限控制规则,管的是哪些请求需要登录、哪些可以随便访问:
- 你写的
.antMatchers("/", "/login", "/register", "/DBDesign", "/index").permitAll():这些页面/路径,不管用户登没登录,所有人都能访问 .antMatchers("/admin/**").hasAuthority("ADMIN"):/admin开头的所有路径,只有拥有ADMIN权限的登录用户才能进.antMatchers("/user/**").hasAuthority("USER"):同理,/user开头的路径需要USER权限.anyRequest().authenticated():除了上面列出来的,其他所有请求都必须登录才能访问- 后面的
formLogin、logout部分是配置自定义登录页、登出逻辑,csrf().disable()是临时关闭CSRF防护(开发时方便,但生产环境记得开回来)
2. SecurityConfiguration里的configure(WebSecurity)
这个配置是用来完全绕过Spring Security过滤器链的,简单说就是这些路径下的东西,Security根本不会去管,直接放行:
你配置的web.ignoring().antMatchers("/resources/**", "/static/**", "/common/**", "/js/**", "/images/**"),意思是这些路径的静态资源(JS、图片、CSS之类的),不管用户登没登录,都能直接访问,不会被Security拦截。
3. WebMvcConfig里的addResourceHandlers
这是Spring MVC的资源映射规则,告诉Spring:当用户请求某个URL时,我该去项目的哪个目录找对应的文件:
- 你写的
/webjars/**对应/webjars/目录(一般是你引入的前端依赖,比如Bootstrap、jQuery这些) /static/**对应classpath:/static/(也就是你项目src/main/resources/static文件夹下的文件)/templates/**对应classpath:/templates/:这里要注意!templates目录默认是放Thymeleaf这类模板文件的,这些文件需要通过控制器跳转才能访问,不能直接通过URL请求,如果你把静态资源(比如JS、图片)放这里了,直接访问肯定404!
你的404问题大概率出在这两个地方
情况1:静态资源的映射没配对
比如你红色标记的资源是/js/xxx.js,实际文件在static/js/xxx.js,但你的addResourceHandlers里只配了/static/**映射到classpath:/static/,那用户请求/js/xxx.js时,Spring MVC不知道这个URL对应static/js/xxx.js,就会返回404。
解决办法:把所有静态资源的URL路径都加到addResourceHandlers里,比如:
@Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry .addResourceHandler("/webjars/**", "/static/**", "/js/**", "/images/**", "/common/**") .addResourceLocations("/webjars/", "classpath:/static/", "classpath:/static/js/", "classpath:/static/images/", "classpath:/static/common/"); }
或者更偷懒的方式(只要静态资源都在static下):
registry.addResourceHandler("/**") .addResourceLocations("classpath:/static/");
不过这种方式要注意,别和你的控制器请求路径冲突了。
情况2:静态资源放错了目录
如果你把红色标记的资源放在了templates目录下,那不管怎么配,直接URL访问都会404,因为templates里的文件是模板,需要通过控制器的return "xxx"来渲染,不能直接访问。赶紧把静态资源移到static目录下!
额外建议:想让所有资源公开?简化配置更省心
如果你的需求是所有静态资源都公开,页面里只有/admin、/user需要权限,那可以这么简化:
- 在
configure(WebSecurity)里把所有静态资源路径都忽略,比如:
@Override public void configure(WebSecurity web) throws Exception { web.ignoring().antMatchers("/static/**", "/js/**", "/images/**", "/css/**", "/webjars/**"); }
- 在
configure(HttpSecurity)里只保留页面的权限规则:
@Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/", "/login", "/register", "/DBDesign", "/index").permitAll() .antMatchers("/admin/**").hasAuthority("ADMIN") .antMatchers("/user/**").hasAuthority("USER") .anyRequest().authenticated() .and() .formLogin() .loginPage("/login") .failureUrl("/login?error=true") .successHandler(sucessHandler) .usernameParameter("email") .passwordParameter("password") .and() .logout() .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) .logoutSuccessUrl("/") .and() .exceptionHandling() .accessDeniedPage("/access-denied"); // 开发时可以关CSRF,生产记得开 // http.csrf().disable(); }
这样静态资源完全绕过Security,页面的权限规则也清晰,不容易出错。
内容的提问来源于stack exchange,提问作者Brarord

