权限校验是一个比较通用的业务需求,一般会通过 Spring AOP 切面 + 自定义权限校验注解 实现统一的接口拦截和权限校验;
常用的认证框架有
框架/工具 | 适用场景 | 主要特点 | 优点 | 缺点 |
Spring Security | 复杂的企业级应用 | 强大的安全功能,与 Spring 集成良好 | 功能全面,安全性强,社区支持广泛 | 学习曲线陡峭,配置繁琐 |
Apache Shiro | 中小型项目 | 轻量级,易于使用 | 简单易用,灵活,适合快速上手 | 功能相对有限,文档不够完善 |
Auth0 | 云端身份管理需求 | 托管服务,功能丰富 | 易于使用,功能强大,适合云端解决方案 | 费用高昂,依赖外部服务 |
Sa-Token | 快速开发的中小型项目 | 轻量级、易用性强,专注于认证和授权 | 轻量级,启动快API 简洁,易于上手灵活性高 | 社区相对较小生态不如 Spring Security 完善 |
Sa-Token以前的文章有使用,需要的可参考Sa-Token常用方法以及整合_satoken-优快云博客
使用aop注解进行权限校验
1.先创建一个AuthCheck注解用于权限校验
@Target(ElementType.METHOD) //只在方法上生效
@Retention(RetentionPolicy.RUNTIME) //运行时生效
public @interface AuthCheck {
/**
* 必须有某个角色
*/
String mustRole() default "";
}
2.创建一个java类进行设置切入点和要操作的内容
@Aspect
@Component
public class AuthInterceptor {
//基于 AOP(面向切面编程)的权限校验逻辑,使用了 Spring 的 @Around 切面方法来拦截带有 @AuthCheck 注解的方法调用,
// 并根据注解中的 mustRole 属性进行权限验证
@Resource
private UserService userService;
/**
* 执行拦截
*
* @param joinPoint 切入点
* @param authCheck 权限校验注解
*/
//会拦截所有带有 @AuthCheck 注解的目标方法。
//authCheck 是 @AuthCheck 注解的参数化引用,用于获取注解实例。
@Around("@annotation(authCheck)")
public Object doInterceptor(ProceedingJoinPoint joinPoint, AuthCheck authCheck) throws Throwable {
//ProceedingJoinPoint joinPoint:这是 Spring AOP 提供的一个接口,
// 代表被拦截的目标方法的连接点。通过它可以调用目标方法(joinPoint.proceed())
//AuthCheck authCheck:这是从注解中提取的 @AuthCheck 实例,用于访问注解的属性值(如 mustRole)。
String mustRole = authCheck.mustRole(); //获取mustRole属性的值
//使用 RequestContextHolder 获取当前线程绑定的请求上下文。
//将其转换为 ServletRequestAttributes 并提取出 HttpServletRequest 对象,用于后续获取登录用户信息。
RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
// 当前登录用户
User loginUser = userService.getLoginUser(request);
UserEnumRole mustRoleEnum = UserEnumRole.getEnumRoleByValue(mustRole);
// 不需要权限,放行
if (mustRoleEnum == null) {
return joinPoint.proceed();
}
// 以下为:必须有该权限才通过
// 获取当前用户具有的权限
UserEnumRole userRoleEnum = UserEnumRole.getEnumRoleByValue(loginUser.getUserRole());
if (userRoleEnum == null) {
throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
}
//检查目标方法是否要求管理员权限(mustRoleEnum 是否为 ADMIN)。如果是,且当前用户不是管理员,则抛出业务异常,拒绝访问。
if (UserEnumRole.ADMIN.equals(mustRoleEnum) && !UserEnumRole.ADMIN.equals(userRoleEnum)) {
throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
}
// 通过权限校验,放行
return joinPoint.proceed();
}
}
使用也比较简单,只需要在需要校验的方法上加上自定义注解即可