spring security角色和权限,不能同时调用.roles().authorities() 作者:马育民 • 2020-08-03 15:07 • 阅读:10177 # 概述 通过下面实验说明问题 ### 实现配置类 同时授予角色和权限,关键代码: ``` .roles("ADMIN")//admin角色,角色一般全大写 .authorities("mng_user");//管理user权限,权限一般小写 ``` 完整代码: ``` package top.malaoshi.stdsecurity.config; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @Configuration @EnableWebSecurity public class WebSecurityConfig2 extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // 将用户名、密码放入内存中 auth.inMemoryAuthentication() // .passwordEncoder(NoOpPasswordEncoder.getInstance())//密码为明文 .withUser("admin")//用户名 .password("{noop}123456")//{noop}表示密码为明文,与上面是同一个含义 .roles("ADMIN")//admin角色,角色一般全大写 .authorities("mng_user");//管理user权限,权限一般小写 } @Override public void configure(WebSecurity web) throws Exception { web.ignoring().antMatchers("/css/**","/js/**","/img/**");//绕开所有的filter,直接跳过验证 } // 安全拦截机制 @Override public void configure(HttpSecurity http) throws Exception { http.csrf().disable()//禁用csrf // .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) // .and() .authorizeRequests()//url权限配置 // .antMatchers("/index.html").permitAll() // 匹配这些路径可以所有人访问 // .antMatchers("/user/**").hasRole("ADMIN") .antMatchers("/user/**").hasAuthority("mng_user") .anyRequest().authenticated() .and() //login部分 .formLogin() .loginPage("/login.html")//指定登录页面。所有url前面必须写/,否则报错 'xxx' is not a valid forward URL .loginProcessingUrl("/login")//security提供的处理登录url,默认是/login // .successForwardUrl("/index.html")//登录成功后跳转的页面,需要额外处理才能使用,否则页面会提示错误 .defaultSuccessUrl("/index.html")//登录成功后重定向的页面 .failureUrl("/login_fails.html")//登录失败跳转的页面 // .failureForwardUrl("/login_fails.html")//登录失败不会转发 .permitAll()//让login部分的url可以任意访问 // // //logout部分 .and() .logout() .logoutSuccessUrl("/login.html")//退出成功访问的页面 .invalidateHttpSession(true)//清空session .permitAll();//让logout部分的url可以任意访问 } } ``` ### Controller 同上 ### 测试 登录后访问Controller,打印如下: ``` org.springframework.security.core.userdetails.User@586034f: Username: admin; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: mng_user ``` 发现只有权限`Granted Authorities: mng_user` # 原因 执行下面代码时, ``` .roles("ADMIN")//admin角色,角色一般全大写 .authorities("mng_user");//管理user权限,权限一般小写 ``` 后一句的权限把前一句的角色覆盖了 ### `.roles("ADMIN")`源码 调用`.roles("ADMIN")`时,执行`org.springframework.security.core.userdetails.User`类的下面方法: ``` public User.UserBuilder roles(String... roles) { List authorities = new ArrayList(roles.length); String[] var3 = roles; int var4 = roles.length; for(int var5 = 0; var5 < var4; ++var5) { String role = var3[var5]; Assert.isTrue(!role.startsWith("ROLE_"), () -> { return role + " cannot start with ROLE_ (it is automatically added)"; }); authorities.add(new SimpleGrantedAuthority("ROLE_" + role)); } return this.authorities((Collection)authorities); } ``` 然后调用了下面方法, ``` public User.UserBuilder authorities(Collection extends GrantedAuthority> authorities) { this.authorities = new ArrayList(authorities); return this; } ``` **注意:** 创建`ArrayList`并赋给成员变量`authorities` ### `.authorities("mng_user")`源码 最终调用下面源码: ``` public User.UserBuilder authorities(Collection extends GrantedAuthority> authorities) { this.authorities = new ArrayList(authorities); return this; } ``` 和上面是同一个方法,创建`ArrayList`并赋给成员变量`authorities` ### 结论 所以调用下面方法时,后一行代码会覆盖前一行代码 ``` .roles("ADMIN")//admin角色,角色一般全大写 .authorities("mng_user");//管理user权限,权限一般小写 ``` # 总结 在开发中,如果有角色和权限概念,推荐调用`.authorities("mng_user","ROLE_ADMIN");`,将角色全大写,有前缀:`ROLE_` 千万不要调用下面代码: ``` .roles("ADMIN")//admin角色,角色一般全大写 .authorities("mng_user");//管理user权限,权限一般小写 ``` 后一行代码会覆盖前一行 原文出处:http://malaoshi.top/show_1EF60Rbhbjun.html