@PreAuthorize 和 @PostAuthorize是SpringSecurity中常用的两个注解,简单了解一下他们的用法吧!
开启验证
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| package com.bill.config;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .passwordEncoder(passwordEncoder()) .withUser("admin") .password(passwordEncoder().encode("123456")) .roles("admin"); auth.inMemoryAuthentication() .passwordEncoder(passwordEncoder()) .withUser("user") .password(passwordEncoder().encode("123456")) .roles("normal"); }
@Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); }
}
|
@PreAuthorize注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| package com.bill.controller;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody;
@Controller @RequestMapping("/hello") public class HelloController {
@GetMapping("/") @ResponseBody public String sayHello() { return "Hello, spring security."; }
@GetMapping("/helloNormal") @ResponseBody @PreAuthorize("hasAnyRole('normal')") public String helloNormal() { return "Hello, normal."; }
@GetMapping("/helloAdmin") @ResponseBody @PreAuthorize("hasAnyRole('admin')") public String helloAdmin() { return "Hello, admin"; } }
|
当@EnableGlobalMethodSecurity(prePostEnabled = true)开启的时候,@PreAuthorize注解生效,支持SpringEL表达式,
1 2 3 4 5
| @PreAuthorize("hasAnyRole("admin", "normal")")
@PreAuthorize("hasRole('admin') AND hasRole('normal')")
|
@PostAuthorize
@PostAuthorize 注解使用并不多,在方法执行后再进行权限验证,适合验证带有返回值的权限,Spring EL 提供返回对象能够在表达式语言中获取返回的对象returnObject。
当@EnableGlobalMethodSecurity(prePostEnabled = true)的时候,@PostAuthorize可以使用:
1 2 3 4 5 6 7 8 9 10 11 12
| @GetMapping("/helloUser") @PostAuthorize("returnObject != null && returnObject.username == authentication.name") public User helloUser() { Object pricipal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); User user; if ("anonymousUser".equals(pricipal)) { user = null; } else { user = (User) pricipal; } return user; }
|
内置表达式:
| 表达式 |
备注 |
| hasRole([role]) |
如果有当前角色, 则返回 true(会自动加上 ROLE_ 前缀) |
| hasAnyRole([role1, role2]) |
如果有任一角色即可通过校验, 返回true,(会自动加上 ROLE_ 前缀) |
| hasAuthority([authority]) |
如果有指定权限, 则返回 true |
| hasAnyAuthority([authority1, authority2]) |
如果有任一指定权限, 则返回true |
| principal |
获取当前用户的 principal 主体对象 |
| authentication |
获取当前用户的 authentication 对象, |
| permitAll |
总是返回 true, 表示全部允许 |
| denyAll |
总是返回 false, 代表全部拒绝 |
| isAnonymous() |
如果是匿名访问, 返回true |
| isRememberMe() |
如果是remember-me 自动认证, 则返回 true |
| isAuthenticated() |
如果不是匿名访问, 则返回true |
| isFullAuthenticated() |
如果不是匿名访问或remember-me认证登陆, 则返回true |
| hasPermission(Object target, Object permission) |
|
| hasPermission(Object target, String targetType, Object permission) |
|
@Secured
当@EnableGlobalMethodSecurity(securedEnabled = true)的时候,@Secured可以使用。
1 2 3 4 5
| @GetMapping("/helloUser") @Secured({"ROLE_admin", "ROLE_normal"}) public String helloUser() { return "hello, user"; }
|
拥有normal或者admin角色的用户都可以访问helloUser()方法。另外需要注意的是这里 匹配的字符串需要添加前缀“ROLE_“,如果我们要求,只有同时拥有admin & normal的用户才能访问helloUser()方法,这时候@Secured就无能为力了。