上面两篇我们重点介绍了如何在代码上集成springSecurity,同时完成登录认证和token认证的过程。我们直到springSecurity处理能帮我们完成认证外,还可以帮助我们完成权限校验的工作,这篇我们来重点介绍下springSecurity是如何实现鉴权的。
一、springSecurity鉴权原理
在 Spring Security 中,权限控制可以通过多种方式进行,包括配置类中的 HttpSecurity 配置和方法级别的注解(如 @PreAuthorize、@PostAuthorize、@Secured 等)。
(1)、FilterSecurityInterceptor过滤器
Spring Security提供了一个核心鉴权过滤器FilterSecurityInterceptor。
FilterSecurityInterceptor主要负责 HttpSecurity
配置中的权限规则校验,如果用户请求URL 资源和配置种校验口可以放行,则通过。FilterSecurityInterceptor本身不直接处理方法级别的注解。
(2)、安全注解
springSecurity是一组过滤器链,当所有过滤器执行完成后,请求就会放行到具体的接口上。
接口上可以通过添加安全注解的方式,更细粒度的控制权限,如(@PreAuthorize、@Secured 等)。如果方法级别的注解不允许访问,请求也将被拒绝。注解由MethodSecurityInterceptor处理实现。
(3)、总结
1、请求到达:
用户发送请求到某个 URL(例如 /product1)。
2、优先HttpSecurity 配置检查:
Spring Security 会首先根据 HttpSecurity 配置进行权限检查。
如果 HttpSecurity 配置中不允许访问该 URL,请求将被拒绝,不会到达控制器方法。
3、控制器方法的注解检查:
如果 HttpSecurity 配置允许访问该 URL,请求将继续到达控制器方法。在控制器方法调用之前,Spring Security 会检查方法级别的注解(如 @PreAuthorize、@Secured 等)。如果方法级别的注解不允许访问,请求也将被拒绝,即使 HttpSecurity 配置允许访问了也不行。
二、鉴权的实现
1、基于核心配置类的鉴权
(1)、httpSecurity中设置鉴权规则
指定匹配的接口或资源,需要角色,权限还是ip等才可以访问。
(2)、webSecurity设置放行白名单
2、基于方法注解鉴权
(1)、开启注解鉴权
需要在配置类中开启注解鉴权
(2)、接口上添加鉴权注解
(1)、@PreAuthorize
注解在接口执行前被校验,校验失败会抛出异常。一般是校验权限用的最多的注解。
常用的参数包含如下:
1、hasAuthority(String)
判断用户是否具有特定权限,相当于配置的
http.authorizeRequests().antMatchers(“/main1.html”).hasAuthority(“admin”)
2、hasAnyAuthority(String …)
判断用户具备给定权限中某一个,就允许访问,相当于配置
http.authorizeRequests().antMatchers(“/admin/read”).hasAnyAuthority(“xxx”,“xxx”)
3、hasRole(String)
判断用户具备给定角色就允许访问,否则出现403,相当于配置的
http.authorizeRequests().antMatchers(“/admin/read”).hasRole(“ROLE_管理员”)
4、注意:
hasRole与hasAuthority的区别:hasRole的值会添加ROLE_开头进行判断,而hasAuthority不会
(2)、@PostAuthorize
注解会在接口执行完成后校验,校验失败会抛出异常。
代码示例:
@GetMapping("/admin")
@PreAuthorize("hasAuthority('p2')") //拥有p2权限才可以访问
public String printAdmin(){
System.out.println("hello admin");
return "admin";
}
@GetMapping("/user")
@PreAuthorize("hasAnyRole('USER')") // 拥有任何一个角色会执行
public String printUser(){
System.out.println("hello user");
return "user";
}
@GetMapping("/admin1")
@PostAuthorize("returnObject.owner == 'admin1'") // 返回属性等于admin1时放行
public SomeObject printAdmin1(){
System.out.println("hello admin1");
return new SomeObject("admin1");
}
@Secured("ROLE_ADMIN") // 具有 ROLE_ADMIN 角色的用户才能调用此方法
public void adminOnlyMethod() {
// 只有具有 ROLE_ADMIN 角色的用户才能调用此方法
}
@PreAuthorize("#id == authentication.principal.id") // 入参id和认证的用户id相同时
public void getUserById(String id) {
// 只有当请求的用户ID与当前认证用户ID相同时,才能调用此方法
}
3、自定义鉴权方法
这个比较灵活,比较推荐使用。自定义校验方法,需要注入spring容器,使用@PreAuthorize指定自定义的这个校验方法。
示例代码:
学海无涯苦作舟!!!