授权
认证
身份认证,就是判断一个一个用户是否为合法用户的处理过程。Spring Security中支持所中不同方式的认证。
授权
授权,即访问控制,控制水能访问那些资源。提前设计好系统权限规则,给认证的用户分配某一个资源的权限,用户根据自己所具有的权限,去执行相应的操作。
用户在认证成功之后会将当前登陆用户信息保存到Authentication对象中,Authentication对象中有一个getAuthorities()方法,用来返回当前登陆用户具备的权限信息,当需要进行权限判断时,就会根据集合返回权限信息调用相应方法进行判断。
我们针对授权可以是“基于角色权限管理”和“基于资源权限管理”,从设计层面上来说,角色和权限是两个完全不同的东西
权限是一些具体的操作,角色则是某些权限的集合。
基于角色权限设计:用户-角色-资源,返回的就是用户的角色
基于资源权限设计就是:用户-权限-资源三者关系,返回就是用户的权限。
基于角色和资源权限设计就是:用户-角色-权限-资源,返回统称为权限。
在Spring Security中,角色和权限处理方式基本上是一致的。唯一区别就是会自动给角色添加ROLE_前缀,而权限则不会自动添加。
权限管理策略
SpringSecurity中为我们提供了两种权限管理策略:
基于过滤器的权限管理(FilterSecurityInterceptor):基于过滤器的权限管理主要是用来拦截HTTP请求,拦截下来之后,根据HTTP请求地址进行权限校验。
基于AOP的权限管理(MethodSecurityInterceptor):基于AOP权限管理主要是用来处理方法级别的权限问题。放需要调用某一个方法时,通过AOP将操作拦截下来,然后判断用户是否具备相关权限。
方法
说明
hasAuthority(String authority)
当前用户是否具备指定权限
hasAnyAuthority(String... authorities)
当前用户是否具备指定权限中的任意一个
hasRole(String role)
当前用户是否具备指定角色
hasAnyRole(String... roles)
当前用户是否具备指定角色中的任意一个
permitAll()
放行所有请求
denyAll()
拒绝所有请求
isAnonymous()
当前用户是否是一个匿名用户
isAuthenticated
当前用户是否已经认证成功
isRememberMe()
当前用户是否通过Remember-Me自动登陆
getAuthorities
当前用户是否既不是匿名用户也不同通过Remember-Me自动登陆
hasPermission(Object target, Object permission)
当前用户是否具备指定目标的指定权限信息
hasPermission(Object targetId, String targetType, Object permission)
当前用户是否具备指定目标的制定权限信息
基于请求的授权
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
httpSecurity.authorizeHttpRequests(authorizeHttpRequests ->
authorizeHttpRequests
.requestMatchers("/admin/role/**").hasRole("ADMIN") // admin/role/** 路径下的请求,需要 ADMIN 角色
.requestMatchers("/admin/auth/**").hasAnyAuthority("ADMIN:API")// admin/auth/** 路径下的请求,需要 ADMIN:API 权限
.requestMatchers("/user/role/**").hasRole("USER") // user/role/** 路径下的请求,需要 USER 角色
.requestMatchers("/user/auth/**").hasAuthority("USER:API") // user/auth/** 路径下的请求,需要 USER:API 权限
.requestMatchers("/login", "/welcome").permitAll() // 所有用户都可以访问
.anyRequest().authenticated()
);
httpSecurity.formLogin(formLogin -> formLogin.loginPage("/login")
.defaultSuccessUrl("/welcome"));
httpSecurity.csrf(AbstractHttpConfigurer::disable).cors(withDefaults());
return httpSecurity.build();
}
/**
* 配置用户信息服务
*/
@Bean
public UserDetailsService userDetailsService() {
InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager();
UserDetails user1 = User.withUsername("admin").password("{noop}123").roles("ADMIN").authorities("ADMIN:API").build();
UserDetails user2 = User.withUsername("user").password("{noop}123").roles("USER").authorities("USER:API").build();
inMemoryUserDetailsManager.createUser(user1);
inMemoryUserDetailsManager.createUser(user2);
return inMemoryUserDetailsManager;
}
基于方法注解的鉴权
在Spring Security6版本中@EnableGlobalSecurity被弃用,取而代之的是@EnableMethedSecurity,默认情况下,会激活pre-post注解,并在内部使用AuthorizationManager。
PostAuthorize
/**
* PostAuthorize 注解的作用是在方法执行后再进行权限验证,这样可以拿到方法的返回值,然后再进行权限验证
* returnObject 表示方法的返回值
*
* @param id 用户id
* @return String
*/
@PostAuthorize("returnObject.startsWith('Rol1e')")
@GetMapping("/stu/role1/{id}")
public String stuAuth1(@PathVariable("id") String id) {
return "Role Hello student!, id=" + id;
}
PostFilter
/**
* PostFilter 注解的作用是在方法执行后再进行权限验证,这样可以拿到方法的返回值,然后可以对返回值进行过滤,然后再进行权限验证
* 例如:下面的例子中,只有返回值的长度大于2的才能访问
* @return String
*/
@PostFilter("filterObject.length() > 2")
@GetMapping("/stu/role2/{id}")
public List<String> stuAuth2() {
List<String> list = new ArrayList<>();
list.add("张三");
list.add("李四");
list.add("王五");
list.add("赵小名");
return list;
}
PostAuthorize:
/**
* PostAuthorize 注解的作用是在方法执行后再进行权限验证,这样可以拿到方法的返回值,然后再进行权限验证
* returnObject 表示方法的返回值
*
* @param id 用户id
* @return String
*/
@PostAuthorize("returnObject.startsWith('Role')")
@GetMapping("/stu/role1/{id}")
public String stuAuth1(@PathVariable("id") String id) {
return "Role Hello student!, id=" + id;
}
PreFilter
/**
* PreFilter 注解的作用是在方法执行前进行权限验证,这样可以拿到方法的参数,然后再进行权限验证
* 例如:下面的例子中,只有参数的长度大于2的才能访问, filterTarget 表示过滤的目标,这里是id
*
* @param id 用户id
* @return String
*/
@PreFilter(value = "filterObject.length() > 2", filterTarget = "id")
@PostMapping("/stu/role3/{id}")
public List<String> stuAuth3(@RequestBody List<String> id) {
List<String> list = new ArrayList<>();
list.add("张三");
list.add("李四");
list.add("王五");
list.add("赵小名");
return list;
}
动态权限
最后更新于
这有帮助吗?