SpringSecurity跟SpringBoot的整合-通过注解控制访问权限

SpringSecurity跟SpringBoot的整合-通过注解控制访问权限
系列文章:
SpringSecurity跟SpringBoot的整合-项目创建
SpringSecurity跟SpringBoot的整合-自定义登录页面
SpringSecurity跟SpringBoot的整合-从数据库中读取用户信息校验
SpringSecurity跟SpringBoot的整合-remember me
我们之前是通过配置规则来配置权限的,如果接口很多,那我们不就要配置N多的规则嘛。
其实在实际开发中,我们应该是控制service层的方法权限
所以,切入点要注意一下,如果是用xml配置的话,要添加到service里,如果你是控制controller层的话,那么就添加到controller里
开启支持注解控制权限
在我们的配置文件上
添加一个
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true, securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
如上代码,开启prePost,jsr250,以及secured
这三种注解方式我们在后面的例子里体现出来
添加注解
我们把controller上的接口,添加一下权限注解
这个是manager接口的
@Controller
public class AdminController {
@PreAuthorize("hasAnyRole('ROLE_ADMIN')")
@GetMapping("/manager")
public String manager() {
return "manager";
}
}
这个是门户的接口
@Controller
public class PortalController {
@PreAuthorize("hasAnyRole('ROLE_REGISTER')")
@GetMapping("/")
public String home(Model model) {
return index(model);
}
@PreAuthorize("hasAnyRole('ROLE_REGISTER')")
@GetMapping("/index")
public String index(Model model) {
String name = SecurityContextHolder.getContext().getAuthentication().getName();
System.out.println("userName -=== > " + name);
Collection<? extends GrantedAuthority> authorities = SecurityContextHolder.getContext().getAuthentication().getAuthorities();
for (GrantedAuthority authority : authorities) {
String role = authority.getAuthority();
System.out.println("role - > " + role);
}
model.addAttribute("userName", name);
return "index";
}
@PreAuthorize("hasAnyRole('ROLE_REGISTER')")
@GetMapping("/list")
public String listContent() {
return "list";
}
@GetMapping("/403")
public String page403() {
return "403";
}
@GetMapping("/loginPage")
public String loginPage() {
return "login";
}
@ResponseBody
@GetMapping("/failure")
public String failure() {
return "failure";
}
}
这种pre开头的,对应的是我们声明prePostEnabled=true这种方式
测试权限
接下来,看看我们的用户-角色-权限
用户表
从这三张表,就可以知道
president-->注册用户、讲师、管理员 BillGates-->注册用户、讲师
所以,BillGates无法访问manager的接口
我们试试看吧!
我们再试试president这个账号吧
okay到这里我们就可以控制住权限了,特定角色的用户才可以访问特定的接口
几种注解方式的说明
- secured
- prePost
- jsr250
securedEnable=true
开启这个注解支持,那么就可以使用@Secured注解了
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Secured {
String[] value();
}
这是这个注解源码,它需要一个字符串数组,也就是权限数组。
@Secured("ROLE_ADMIN")
这就表明被注解的地方需要有管理员权限才可以访问
@Secured({"ROLE_ADMIN","ROLE_REGISTER"})
这表示注册用户或者管理员就可以访问
但是,某些时候,我们需要组合权限呢?这就需要使用prePost的注解方式来解决了
因为secured的注解方式不支持EL表达式
而且必须以ROLE开头描述角色
prePostEnable=true
适用于方法级别的权限描述
支持内置表达式
开启这个注解支持以后,它提供了四种注解
- @PreAuthorize
我们也比较常用这种来控制权限
比如看这里吧,就给出这么多提示了
实现前面的功能,可以省略ROLE前缀,如果你的数据库里的权限是ROLE_ADMIN,那么你可以直接写hasRole('ADMIN')即可
@PreAuthorize("hasRole('ADMIN')")
或者这样
@PreAuthorize("hasAnyRole('REGISTER')")
如果需要多个权限呢?
@PreAuthorize("hasRole('ADMIN') and hasRole('REGISTER')")
- @PostAuthorize 返回数据的权限控制,其实权限吧,灵活一点就是条件了,这个用得少,想了解自行查一下吧。
- @PreFilter 这个也用得少,对参数进行过滤
- @PostFilter 对返回的数据进行过滤
jsr250Enable=true
这个则是比较简单,只有三个注解
- @DenyAll 拒绝访问,这个用得比较少咯
- @PermitAll 允许所有访问
- @RolesAllowed 允许对应的角色进行访问,这里面也是可以省略ROLE前缀
@RolesAllowed("REGISTER")
这样就允许注册用户访问了。
okay,到这里我们基本上就是把权限控制位了。方式很简单,同学们可以去看别人的项目,或者去了解一下内置表达式。这样子控制权限就很灵活了。