Spring Boot项目如何正确配置Spring Security实现页面权限控制
配置错误点
你当前的权限配置逻辑有三处问题,完全不符合需求:
.anyRequest().authenticated()规则强制所有请求必须认证后才能访问,直接把所有公共页面、静态资源、登录页全部拦截,匿名用户无法访问任何非鉴权路径- 仅指定了登录页路径,但没有给登录页开放匿名访问权限,会触发未登录→跳登录页→登录页也要登录→再跳登录页的重定向死循环
- 没有放行静态资源路径,static目录下的css、js、存放在static的图片资源会被拦截,页面样式、交互会全部失效
- 注意:Thymeleaf的
templates目录下的文件是受保护的模板资源,无法被直接通过物理路径访问,所有权限匹配的是Controller层的请求映射路径,不是模板文件的磁盘路径
可用的完整配置
@Configuration @EnableWebSecurity public class SecSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(final HttpSecurity http) throws Exception { http // 开发阶段可先关闭CSRF,避免普通表单提交报403,生产环境按需开启 .csrf().disable() .authorizeRequests() // 放行所有静态资源 .antMatchers("/static/**", "/images/**").permitAll() // 放行所有不需要登录就能访问的公共页面:首页、注册页、登录页 .antMatchers( "/", "/index", "/home", "/firstPage", "/inscriptionForm", "/loginPage.html" ).permitAll() // userOnly目录下的所有请求,必须拥有USER角色才可访问 .antMatchers("/userOnly/**").hasRole("USER") // 其余所有请求,只要登录即可访问,不限制角色 .anyRequest().authenticated() .and() .formLogin() // 自定义登录页路径 .loginPage("/loginPage.html") // 登录表单提交的默认处理路径,和表单action保持一致即可,默认值为/login .loginProcessingUrl("/login") // 登录成功后默认跳转首页 .defaultSuccessUrl("/home", true) // 登录失败返回登录页并携带错误参数 .failureUrl("/loginPage.html?error=true") // 放行登录相关的所有请求 .permitAll() .and() // 配置退出登录逻辑 .logout() .logoutUrl("/logout") .logoutSuccessUrl("/loginPage.html?logout=true") .permitAll(); } }
配套配置说明
如果你没有为每个页面单独写Controller方法做视图返回,可以加一个MVC配置类,直接把请求路径和templates下的模板做绑定,不需要写冗余的Controller方法:
@Configuration public class MvcConfig implements WebMvcConfigurer { @Override public void addViewControllers(ViewControllerRegistry registry) { // 公共页面映射 registry.addViewController("/loginPage.html").setViewName("loginPage"); registry.addViewController("/").setViewName("index"); registry.addViewController("/index").setViewName("index"); registry.addViewController("/home").setViewName("home"); registry.addViewController("/firstPage").setViewName("firstPage"); registry.addViewController("/inscriptionForm").setViewName("inscriptionForm"); // userOnly目录下页面映射 registry.addViewController("/userOnly/help").setViewName("userOnly/help"); registry.addViewController("/userOnly/menu").setViewName("userOnly/menu"); registry.addViewController("/userOnly/newDocForm").setViewName("userOnly/newDocForm"); registry.addViewController("/userOnly/profil").setViewName("userOnly/profil"); } }
避坑提醒
hasRole("USER")方法会自动在角色名前拼接ROLE_前缀,如果你数据库里存储的用户角色字段值是USER,要改成ROLE_USER,或者换成hasAuthority("USER")做权限匹配,后者不会自动拼接前缀- 不要把templates目录配置成静态资源目录,否则会直接泄露模板源码
- 如果登录后访问userOnly路径报403,优先检查当前登录用户是否被正确授予了对应角色
内容的提问来源于stack exchange,提问作者Rune
相关产品推荐
相关产品推荐

