实验一:只授予权限
实现配置类
只授予一个权限,关键代码:
.authorities("mng_user");
url需要mng_user权限才能访问,关键代码:
.antMatchers("/user/**").hasAuthority("mng_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
package top.malaoshi.stdsecurity.controller;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/user")
public class UserController {
@RequestMapping(value = "/user")
public String getUser(){
User user = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
System.out.println(user);
return "success";
}
}
测试
登录后访问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可以看出有mng_user权限
实验二:只授予角色
实现配置类
只授予ADMIN角色,关键代码:
.roles("ADMIN")//admin角色,角色一般全大写
url只有ADMIN角色才能访问,关键代码:
.antMatchers("/user/**").hasRole("ADMIN")
完整代码:
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")
.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")//登录成功后重定向的页面
// .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: ROLE_ADMIN
没有角色ADMIN,只有权限Granted Authorities: ROLE_ADMIN,说明在spring security中,授予的角色,是在前面加上前缀ROLE_,然后放入到 权限 中
原因
执行.roles("ADMIN");,调用了org.springframework.security.core.userdetails.User类的下面方法:
public User.UserBuilder roles(String... roles) {
List<GrantedAuthority> 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);
}
通过authorities.add(new SimpleGrantedAuthority("ROLE_" + role));可以看出加上了前缀ROLE_
结论
在spring security中,只有权限,没有角色,所谓的角色,是在前面加上前缀ROLE_,然后放入到 权限 中
判断角色时:.hasRole("ADMIN"),前面不需要加ROLE_
总结
在开发中,如果有角色和权限概念,推荐调用.authorities("mng_user","ROLE_ADMIN");,角色全大写,有前缀:ROLE_
千万不要调用下面代码:
.roles("ADMIN")//admin角色,角色一般全大写
.authorities("mng_user");//管理user权限,权限一般小写
后一行代码会覆盖前一行,详见:
https://www.malaoshi.top/show_1EF60Rbhbjun.html