Springboot通过注解+切面实现接口权限校验
主要说一下在对接口请求时,如何用注解+切面去拦截校验当前登录用户是否有访问权限
1.首先创建注解 @HasPermission ,跟普通注解创建方式基本一致
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface HasPermission {
String permission() default "";
}
2.创建一个切面,用来请求接口时做前置校验
主要思路:
先获取到注解@HasPermission 的内容,从redis中拿到当前用户角色的所有权限,如果当前用户不是超级管理员并且权限中不包含要请求的接口权限,就返回未授权。
用户在登录时会查询数据库将角色的所有权限存入redis,如果对角色做权限修改时,同步修改redis,这样每次请求接口时,都能从redis中拿到最新的权限。
@Aspect
@Component
public class PermissionAspect {
@Resource
private TokenDTO tokenDTO;
@Resource
private StringRedisTemplate stringRedisTemplate;
@Resource
private RoleRepository roleRepository;
/**
* 前置通知
* @param joinPoint
*/
@Before("pointCut()")
public void checkPermission(JoinPoint joinPoint) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
HasPermission annotation = method.getAnnotation(HasPermission.class);
if (annotation != null) {
String permission = annotation.permission();
roleRepository.findById(tokenDTO.getRoleId()).ifPresent(roleDO -> {
//从redis中取出当前角色的所有权限
String permissions = stringRedisTemplate.opsForValue().get(roleDO.getId());
if (!roleDO.getCode().equals(UserConstant.ROLE_SUPER_ADMIN) && permissions != null) {
if (!permissions.contains(permission)) {
throw new UnauthorizedException("unauthorized");
}
}
});
}
}
/**
* 切点
*/
@Pointcut("@annotation(com.******************.annotation.HasPermission)")
public void pointCut() {
}
}
3.接口上方加上注解 @HasPermission(permission = “country:list”),这样每次请求接口时有提前校验,“country:list” 要和数据库中保存的权限内容保持一致,这样才能做判断
@HasPermission(permission = "country:list")
@GetMapping("/countries/list")
public Result filterCountry(CountryFilterDTO countryFilterDto, CustomPageable pageable) {
return countryService.filterCountry(countryFilterDto, pageable);
}
另外,还有一种权限校验的方式,可以参考若依的开源,类似这种
@PreAuthorize(“@ss.hasPermi(‘system:role:edit’)”)
有需要可以去看看,这里就不多说了