在前两节中我们都是对url请求路径的来进行授权(基于角色,基于资源),当然security2以后还提供了基于方法的授权可以在任何@Configuration实列上通过@EnableGlobalMethodSecurity(securedEnabled = true)注解来启动方法的授权,下面会介绍@Secured(),@PreAuthorize()方法主角授权的使用
一,@Secured()的使用:这个注解配置在方法上是基于角色的授权模式,也就是只有用户拥有指定角色才能访问指定资源
第一步:在配置类上加上@EnableGlobalMethodSecurity(securedEnabled = true)注解,然后注释掉之前访问路径的配置
@EnableWebSecurity
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true)
public class webSecurityConfig extends WebSecurityConfigurerAdapter {
//密码编译比对方式
@Bean
public BCryptPasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
//访问路径配置
@Override
protected void configure(HttpSecurity http) throws java.lang.Exception {
//hasAuthority : 基于资源授权 hasRole:基于角色授权
http
.csrf().disable() //去除csrf攻击的配置,以便除get请求方式,其他请求方式也能访问接口
.authorizeRequests()
// .antMatchers("/auth/hello").hasAuthority("resource_1") //给访问的地址加上资源权限限制,只有用户有这个资源访问权限时才能访问
// .antMatchers("/auth/home").hasAuthority("resource_2")
// .antMatchers("/auth/admin").hasAuthority("resource_3")
.antMatchers("/test/health").permitAll() //此路径不需要经过过认证,可以不登录直接请求;注意不要放在上面的代码之前不然上面代码会失效,带通配符的url顺序也要注意 如 auth/login 应该放在auth/**的前面,也就是范围越大的越在后面
.anyRequest().authenticated() //除配置的/test/health路径其他请求都需要认证
.and()
.formLogin() //允许表单登陆
.successForwardUrl("/sys/login") //自定义表单登陆成功后的跳转路径
.and()
.logout()
.logoutUrl("/sys/logOut");
}
//基于内存的用户配置
// @Override
// protected void configure(AuthenticationManagerBuilder auth) throws java.lang.Exception {
// //创建三个用户到内存中,并给他们分配角色
// auth.inMemoryAuthentication()
// .withUser("zhangsan").password(this.passwordEncoder().encode("123456")).roles("GUEST");
// auth.inMemoryAuthentication()
// .withUser("lisi").password(this.passwordEncoder().encode("123456")).roles("USER");
// auth.inMemoryAuthentication()
// .withUser("wangwu").password(this.passwordEncoder().encode("123456")).roles("USER","ADMIN");
// }
}
第二步:将用户授权改为角色授权(.roles(“ADMIN”))
@Service
public class SpringDataUserDetailsServiceImpl implements UserDetailsService {
private static Logger logger = Logger.getLogger(SpringDataUserDetailsServiceImpl.class);
@Autowired
private UserDao userDao;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
logger.info("++进入SpringDataUserDetailsServiceImpl++ username = "+username);
UserDo u = new UserDo();
u.setUserName(username);
UserDo user = userDao.selectOne(new QueryWrapper<>(u));
logger.info("查询到的用户信息:"+user.toString());
if(Objects.isNull(user)){
//没有查到用户交给provider来抛异常
return null;
}
UserDetails userDetails = User
.withUsername(user.getUserName())
.password(user.getPassword())
// .authorities("resource_1")
.roles("ADMIN")
.build();
logger.info("++退出SpringDataUserDetailsServiceImpl++");
return userDetails;
}
}
第三步:在授权通过后需要访问的资源上的方法上面加上@Secured()注解
注意:注解里面的参数:如果是角色授权那么参数需要以ROLE开头如:“ROLE_XXXX”
@GetMapping("/auth/home")
@ResponseBody
@Secured("ROLE_USER")
public String test2(){
logger.info("+++++++++++++++++++++++++++++++请求成功TEST_USER+++++++++++++++++++++++++++++++++++");
return "USER";
}
@GetMapping("/auth/admin")
@ResponseBody
@Secured("ROLE_ADMIN")
public String test3(){
logger.info("+++++++++++++++++++++++++++++++请求成功TEST_ADMIN+++++++++++++++++++++++++++++++++++");
return "ADMIN";
}
第五步:测试,用户登陆因为用户角色是写死的每个用户登陆都是ADMIN角色,那么,用户只能访问test3方法,而不能访问test2方法
@Secured的其他参数:

二, @PreAuthorize / @PostAuthorize的使用:这两个注解的功能是差不多的,只是区别在于@PreAuthorize是在执行方法之前进行权限或角色的校验,而@PostAuthorize是在方法执行玩之后在进行校验,也就是校验的时机不一样
第一步:配置类上配置开启注解@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true) 注意:记得配置prePostEnabled = true不然注解会不生效
@EnableWebSecurity
@Configuration
//@EnableGlobalMethodSecurity(securedEnabled = true)
@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)
public class webSecurityConfig extends WebSecurityConfigurerAdapter {
//密码编译比对方式
@Bean
public BCryptPasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
//访问路径配置
@Override
protected void configure(HttpSecurity http) throws java.lang.Exception {
//hasAuthority : 基于资源授权 hasRole:基于角色授权
http
.csrf().disable() //去除csrf攻击的配置,以便除get请求方式,其他请求方式也能访问接口
.authorizeRequests()
// .antMatchers("/auth/hello").hasAuthority("resource_1") //给访问的地址加上资源权限限制,只有用户有这个资源访问权限时才能访问
// .antMatchers("/auth/home").hasAuthority("resource_2")
// .antMatchers("/auth/admin").hasAuthority("resource_3")
.antMatchers("/test/health").permitAll() //此路径不需要经过过认证,可以不登录直接请求;注意不要放在上面的代码之前不然上面代码会失效,带通配符的url顺序也要注意 如 auth/login 应该放在auth/**的前面,也就是范围越大的越在后面
.anyRequest().authenticated() //除配置的/test/health路径其他请求都需要认证
.and()
.formLogin() //允许表单登陆
.successForwardUrl("/sys/login") //自定义表单登陆成功后的跳转路径
.and()
.logout()
.logoutUrl("/sys/logOut");
}
//基于内存的用户配置
// @Override
// protected void configure(AuthenticationManagerBuilder auth) throws java.lang.Exception {
// //创建三个用户到内存中,并给他们分配角色
// auth.inMemoryAuthentication()
// .withUser("zhangsan").password(this.passwordEncoder().encode("123456")).roles("GUEST");
// auth.inMemoryAuthentication()
// .withUser("lisi").password(this.passwordEncoder().encode("123456")).roles("USER");
// auth.inMemoryAuthentication()
// .withUser("wangwu").password(this.passwordEncoder().encode("123456")).roles("USER","ADMIN");
// }
}
第二步:接口配置注解
@GetMapping("/auth/hello")
@ResponseBody
//@Secured("ROLE_GUEST")
//@PreAuthorize("isAnonymous()")
public String test1(){
logger.info("+++++++++++++++++++++++++++++++请求成功TEST_GUEST+++++++++++++++++++++++++++++++++++");
return "GUEST";
}
@GetMapping("/auth/home")
@ResponseBody
//@Secured("ROLE_USER")
@PreAuthorize("hasAuthority('resource_1')") //拥有resource_1权限才能访问
//@PreAuthorize("hasRole('USER')") //@PreAuthorize基于角色的授权
public String test2(){
logger.info("+++++++++++++++++++++++++++++++请求成功TEST_USER+++++++++++++++++++++++++++++++++++");
return "USER";
}
@GetMapping("/auth/admin")
@ResponseBody
//@Secured("ROLE_ADMIN")
@PreAuthorize("hasAnyAuthority('resource_2','resource_3')") //拥有resource_2 或者 resource_3权限才能访问
//@PreAuthorize("hasAuthority('resource_2') and hasAuthority('resource_3')") //拥有resource_2 以及 resource_3权限才能访问
//@PreAuthorize("hasRole('ADMIN')") //@PreAuthorize基于角色的授权
public String test3(){
logger.info("+++++++++++++++++++++++++++++++请求成功TEST_ADMIN+++++++++++++++++++++++++++++++++++");
return "ADMIN";
}
test1方法不需要任何校验,test2方法需要有resource_1的权限,test3需要有resource_2和resource_3的权限
本文介绍了SpringSecurity中基于方法授权的使用,包括@Secured和@PreAuthorize/@PostAuthorize。首先讲解了@Secured注解的配置步骤,通过角色进行授权,然后详细阐述了@PreAuthorize和@PostAuthorize的差异,它们分别在方法执行前后进行权限校验。
265

被折叠的 条评论
为什么被折叠?



