From c16d71e6e92aa179d13974db84b7d6fb1a2450c9 Mon Sep 17 00:00:00 2001 From: myh Date: Mon, 6 Nov 2023 18:40:32 +0800 Subject: [PATCH] =?UTF-8?q?RBAC=E6=9D=83=E9=99=90=E6=8E=A7=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/example/springdemo/utils/Result.java | 36 ++++++++ .../utils/RoleVerificationAnnotation.java | 15 ++++ .../utils/RoleVerificationAspect.java | 86 +++++++++++++++++++ 3 files changed, 137 insertions(+) create mode 100644 src/main/java/com/example/springdemo/utils/Result.java create mode 100644 src/main/java/com/example/springdemo/utils/RoleVerificationAnnotation.java create mode 100644 src/main/java/com/example/springdemo/utils/RoleVerificationAspect.java diff --git a/src/main/java/com/example/springdemo/utils/Result.java b/src/main/java/com/example/springdemo/utils/Result.java new file mode 100644 index 0000000..e000c59 --- /dev/null +++ b/src/main/java/com/example/springdemo/utils/Result.java @@ -0,0 +1,36 @@ +package com.example.springdemo.utils; + +import lombok.*; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +import java.io.Serializable; + +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Setter +public class Result implements Serializable { + private Integer status = 0; + private String message = ""; + private T data; + + public Result(Integer status, String message) { + this.status = status; + this.message = message; + } + + public Result(Integer status) { + this.status = status; + } + + @Contract("_, _, _ -> new") + public static @NotNull Result of(Integer status, String message, T data) { + return new Result<>(status, message, data); + } + + @Contract(value = "_, _ -> new", pure = true) + public static @NotNull Result of(Integer status, String message) { + return Result.of(status, message, null); + } +} diff --git a/src/main/java/com/example/springdemo/utils/RoleVerificationAnnotation.java b/src/main/java/com/example/springdemo/utils/RoleVerificationAnnotation.java new file mode 100644 index 0000000..84561dc --- /dev/null +++ b/src/main/java/com/example/springdemo/utils/RoleVerificationAnnotation.java @@ -0,0 +1,15 @@ +package com.example.springdemo.utils; + +// 在Controller中使用该注解,可以实现权限验证 + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +@Target({java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.TYPE}) +@Retention(java.lang.annotation.RetentionPolicy.RUNTIME) +public @interface RoleVerificationAnnotation { + //有权限访问的角色ID + long[] RoleIDList() default {1}; + + long[] UserIDList() default {}; +} diff --git a/src/main/java/com/example/springdemo/utils/RoleVerificationAspect.java b/src/main/java/com/example/springdemo/utils/RoleVerificationAspect.java new file mode 100644 index 0000000..438906b --- /dev/null +++ b/src/main/java/com/example/springdemo/utils/RoleVerificationAspect.java @@ -0,0 +1,86 @@ +package com.example.springdemo.utils; + +import com.example.springdemo.entities.Users; +import jakarta.servlet.http.HttpServletRequest; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.Signature; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.jetbrains.annotations.NotNull; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import java.lang.reflect.Method; + +//角色权限控制AOP +@Component +@Aspect +public class RoleVerificationAspect { + @Pointcut("@annotation(com.example.springdemo.utils.RoleVerificationAnnotation)") + public void roleVerification() { + } + + @Around("roleVerification()") + public Object around(@NotNull ProceedingJoinPoint joinPoint) throws Throwable { + Signature signature = joinPoint.getSignature(); + MethodSignature methodSignature = (MethodSignature) signature; + // 获取正在访问的方法 + Method executingMethod = methodSignature.getMethod(); + RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); + ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes; + Object result; + String message = "Permission denied"; + if (executingMethod.getReturnType().getTypeName().contains(Result.class.getSimpleName())) { + result = Result.of(404, message); + } else { + result = message; + } + + if (servletRequestAttributes == null) { + return result; + } + HttpServletRequest request = servletRequestAttributes.getRequest(); + Integer userID = null; + Integer roleID = null; + //RolesPermissions rolesPermissions = (RolesPermissions) request.getSession().getAttribute("rolesPermissions"); + Users users = (Users) request.getSession().getAttribute("users"); + if (users != null) { + userID = users.getId().intValue(); + roleID = users.getRoles().getId().intValue(); + } + RoleVerificationAnnotation roleVerificationAnnotation = executingMethod.getAnnotation(RoleVerificationAnnotation.class); + //获取注解中的types字段 + long[] rolesIdList = roleVerificationAnnotation.RoleIDList(); + long[] userIdList = roleVerificationAnnotation.UserIDList(); + //判断是否有权限访问 + boolean hasPermission = false; + //是否需要进行校验,如果注解中的types为空,即用户列表和角色列表同时为空,则不进行校验 + boolean needVerify = rolesIdList.length != 0 || userIdList.length != 0; + if (needVerify) { + for (long roleId : rolesIdList) { + if (roleID != null && roleID == roleId) { + hasPermission = true; + break; + } + } + for (long userId : userIdList) { + if (userID != null && userID == userId) { + hasPermission = true; + break; + } + } + } else { + hasPermission = true; + } + + if (hasPermission) { + result = joinPoint.proceed(); + } + + return result; + } +}