目录
🍻前言
🍸一、鉴权(Authorization)
🍺二、功能实现
2.1 环境准备
2.2 代码实现
2.3 测试接口
🍹三、测试功能
3.1 传递 admin 请求
3.2 传递普通 user 请求
🍻四、章末
🍻前言
小伙伴们大家好,最近有一段时间没更了,有一部分是工作上的原因,还有一部分生活上的小事给耽搁了,之前的文章链接如下,这次继续来学习下 Spring EL 表达式的另一种方式,结合切面类实现鉴权的功能;
【Spring EL<一>✈️ 】SL 表达式的应用-CSDN博客
🍸一、鉴权(Authorization)
也称为授权,是系统安全中的一个重要环节。用于确定已经通过认证的用户是否有权限访问某个资源或执行某个操作。鉴权确保只有具有适当权限的用户可以执行特定的操作,从而保护系统的资源和数据。
下面是一些常见的鉴权方式
基于角色的访问控制(RBAC):
- 用户被赋予一个或多个角色,每个角色拥有一组权限。
- 鉴权时根据用户的角色来决定其是否有权限执行某操作。
基于属性的访问控制(ABAC):
- 检查用户属性、环境属性、资源属性等多种因素。
- 使用这些属性和策略规则来进行复杂的鉴权决策。
访问控制列表(ACL):
- 每个资源有一个列表,列出哪些用户或系统进程对该资源有哪些权限。
- 直接针对资源的授权管理。
🍺二、功能实现
本地实现的是基于角色访问控制的鉴权
2.1 环境准备
创建一个简单的 Springboot 项目,确保可以正常启动
引入AOP 的依赖以及打开使用权限
2.2 代码实现
2.2.1 注解定义
简单定义了一个注解,指明了该注解的作用域为方法上,并且运行时可存在
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CheckPermission {
String value();
}
2.2.2 注解切面类实现
这里没有使用切入点(@PointCut),是因为该切面类中只有一个 @Before 操作,如果有多个操作,适合使用 @PointCut 标注,就不用每个方法上都加 "@annotation(com.example.demo.testCode.springel.CheckPermission)" 了
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
@Aspect
@Component
public class PermissionAspect {
@Before("@annotation(com.example.demo.testCode.springel.CheckPermission)")
public void checkUserPermission(JoinPoint joinPoint) throws Throwable {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
CheckPermission checkPermission = method.getAnnotation(CheckPermission.class);
String spelExpression = checkPermission.value();
// 使用Spring EL表达式解析器
ExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext();
// 将方法参数放入上下文中
Object[] args = joinPoint.getArgs();
String[] paramNames = signature.getParameterNames();
for (int i = 0; i < args.length; i++) {
context.setVariable(paramNames[i], args[i]);
}
// 模拟权限检查逻辑
Boolean hasPermission = parser.parseExpression(spelExpression).getValue(context, Boolean.class);
if (!hasPermission) {
throw new SecurityException("User does not have permission to perform this action");
}
}
}
2.3 测试接口
简单的暴露一个接口供测试使用,这里使用的 SpringEL 表达式是“identity == admin" ,就是简单的判断下当前访问该接口的用户的身份是否为 admin,当然这只是一个接口,别的接口可以随意改变鉴权方式以及权限要求
@GetMapping("/checkPermission")
@CheckPermission(value = "#identity == 'admin'")
public void checkPermission(String identity){
// 业务逻辑
System.out.println("Reading sensitive data for user: " + identity);
}
🍹三、测试功能
3.1 传递 admin 请求
模拟 admin 用户访问该接口,结果如图,通过了切面类的 SpringEL 表达式校验
3.2 传递普通 user 请求
模拟普通用户请求访问该接口,结果如图所示,普通用户请求被拦截
这里只是简单的打印了日志,实际应用中可操作空间很大,比如不同的用户执行不同的业务逻辑,或者不同的用户抛出不同的异常信息,再用全局异常处理器实现不同的提示操作等
🍻四、章末
文章到这里就结束了~