需求描述
业务系统的后台管理对应两种类型的admin角色: SUPERADMIN, ADMIN;对于一些操作只有SUPERADMIN才有权限,比如添加新的ADMIN。
为了灵活方便,定义了一个注解,如果某些接口需要某些role才能操作,就加上相应的注解。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AdminRoleCheck {
AdminRole requiredRole() default AdminRole.ADMIN;
}
api代码
@AdminRoleCheck(requiredRole = AdminRole.SUPERADMIN)
@PostMapping("/private/admin/add")
public Response<Void> addAdmin(@RequestParam String username,
@RequestParam String password,
@RequestParam(required = false, defaultValue = "ADMIN") AdminRole role) {
return Response.simpleExecute(() -> adminService.addAdmin(username, password, role));
}
AOP实现的两种方式
从上面代码中可以看到,注解AdminRoleCheck需要一个参数,在校验逻辑中我们需要考虑取出注解中的requiredRole的值,和当前登陆用户的角色进行对比,如果相等,就放行,否则就终止。
1 通过@Before注解
@Aspect
@Component
@Slf4j
public class AuthAop {
@Autowired
AdminHelper adminHelper;
@Before(value = "@annotation(check)", argNames = "check")
public void doAdminRoleCheck(AdminRoleCheck check) {
Admin admin = adminHelper.currentAdmin();
if (Objects.isNull(admin) || admin.getRole() != check.requiredRole()) {
throw new BusinessException("Permission denied for this action", ResponseCode.PERMISSION_DENIED);
}
}
}
2 通过PointCut
@Aspect
@Component
@Slf4j
public class AuthAop {
@Autowired
AdminHelper adminHelper;
@Pointcut("@annotation(com.binance.bcf.annotations.AdminRoleCheck)")
public void adminRoleCheck() {
}
@Around(value = "adminRoleCheck()")
public void doAdminRoleCheck(ProceedingJoinPoint joinPoint) throws Throwable {
AdminRoleCheck annotation = ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotation(AdminRoleCheck.class);
Admin admin = adminHelper.currentAdmin();
if (Objects.isNull(admin) || admin.getRole() != annotation.role()) {
throw new BusinessException("Permission denied for this action", ResponseCode.PERMISSION_DENIED);
}
joinPoint.proceed();
}
}