目录
用户登录后会根据用户的身份进行角色划分,比如登录图书馆系统,一般就有管理员和普通学生等不同角色。
用户的一个操作实际上就是在访问我们提供的`接口`(编写的对应访问路径的 Servlet),比如登陆,就需要调用`/login`接口,退出登陆就要调用/`logout`接口,因此,决定用户能否使用某个功能,只需要决定用户是否能够访问对应的 Servlet
SpringSecurity 有两种授权方式
- 基于权限的授权:只要拥有某权限的用户,就可以访问某个路径
- 基于角色的授权:根据用户属于哪个角色来决定是否可以访问某个路径
基于角色的授权
需要配置 SpringSecurity决定哪些角色可以访问哪些页面
http
.authorizeRequests()
.antMatchers("/static/**").permitAll()
.antMatchers("/index").hasAnyRole("user", "admin") //index页面可以由user或admin访问
.anyRequest().hasRole("admin") //除了上面以外的所有内容,只能是admin访问
可以创建一个实体类来接收用户的信息
@Data
public class AuthUser {
String username;
String password;
String role;
}
修改一下用于验证用户信息的service
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
AuthUser user = mapper.getPasswordByUsername(s);
if(user == null)
throw new UsernameNotFoundException("登录失败,用户名或密码错误!");
return User
.withUsername(user.getUsername())
.password(user.getPassword())
.roles(user.getRole())
.build();
}
基于权限的授权
基于权限的授权与角色类似,需要以`hasAnyAuthority`或`hasAuthority`进行判断
例子
.anyRequest().hasAnyAuthority("page:index")
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
AuthUser user = mapper.getPasswordByUsername(s);
if(user == null)
throw new UsernameNotFoundException("登录失败,用户名或密码错误!");
return User
.withUsername(user.getUsername())
.password(user.getPassword())
.authorities("page:index")
.build();
}
使用注解判断权限
首先需要在相应的配置类(注意只是在 Mvc 的配置类上添加,就只针对 Controller 进行过滤,因为所有的 Controller 是由 Mvc 配置类进行注册的,如果需要为 Service 或其他 Bean 也启用权限判断,则需要在 Security 的配置类上添加)上开启
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
接着就可以直接在需要添加权限验证的请求映射上添加注解
通过添加`@PreAuthorize`注解,在执行之前判断判断权限,如果没有对应的权限或是对应的角色,将无法访问页面
@PreAuthorize("hasRole('user')") //判断是否为user角色,只有此角色才可以访问
@RequestMapping("/index")
public String index(){
return "index";
}
同样的还有`@PostAuthorize`注解,它是在方法执行之后再进行拦截
@PostAuthorize("hasRole('user')")
@RequestMapping("/index")
public String index(){
System.out.println("执行了");
return "index";
}
只要是由 Spring 管理的 Bean 都可以使用注解形式来控制权限,只要不具备访问权限,那么就无法执行方法并且会返回 403 页面
@Service
public class UserService {
@PreAuthorize("hasAnyRole('user')")
public void test(){
System.out.println("成功执行");
}
}
过滤器
使用`@PreFilter`和`@PostFilter`对集合类型的参数或返回值进行过滤
@PreFilter("filterObject.equals('zzp')") //filterObject代表集合中每个元素,只要满足条件的元素才会留下
public void test(List<String> list){
System.out.println("成功执行"+list);
}
@RequestMapping("/index")
public String index(){
List<String> list = new LinkedList<>();
list.add("zzp")
service.test(list);
return "index";
}
当有多个集合时,需要使用`filterTarget`进行指定
@PreFilter(value = "filterObject.equals('lbwnb')", filterTarget = "list2")
public void test(List<String> list, List<String> list2){
System.out.println("成功执行"+list);
}