From 75d07779c1d03a25d5ebb2cde13f057d1b628bab Mon Sep 17 00:00:00 2001 From: ArgonarioD Date: Fri, 13 Jan 2023 22:29:36 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E4=BA=86=E6=96=B0=E7=9A=84?= =?UTF-8?q?=E9=89=B4=E6=9D=83=E5=88=87=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../aop/ProjectAuthorizeAOP.java | 71 +++++++++++++++++++ .../exception/BadRequestException.java | 2 +- .../exception/BusinessException.java | 12 ++++ .../exception/ForbiddenException.java | 2 +- .../exception/TooManyRequestException.java | 2 +- .../exception/UnauthorizedException.java | 2 +- .../interceptor/TokenInterceptor.java | 2 - .../projectmanagement/utils/TokenUtils.java | 4 +- .../utils/http/HttpUtils.java | 12 ++++ .../rmdjzz/projectmanagement/UtilTests.java | 12 ++++ 10 files changed, 114 insertions(+), 7 deletions(-) create mode 100644 src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/aop/ProjectAuthorizeAOP.java create mode 100644 src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/exception/BusinessException.java diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/aop/ProjectAuthorizeAOP.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/aop/ProjectAuthorizeAOP.java new file mode 100644 index 0000000..ad76574 --- /dev/null +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/aop/ProjectAuthorizeAOP.java @@ -0,0 +1,71 @@ +package cn.edu.hfut.rmdjzz.projectmanagement.aop; + +import cn.edu.hfut.rmdjzz.projectmanagement.annotation.ProjectAuthorize; +import cn.edu.hfut.rmdjzz.projectmanagement.exception.ForbiddenException; +import cn.edu.hfut.rmdjzz.projectmanagement.service.IProjectGroupService; +import cn.edu.hfut.rmdjzz.projectmanagement.service.IProjectService; +import cn.edu.hfut.rmdjzz.projectmanagement.utils.TokenUtils; +import cn.edu.hfut.rmdjzz.projectmanagement.utils.http.HttpUtils; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.expression.ExpressionParser; +import org.springframework.expression.spel.standard.SpelExpressionParser; +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 org.springframework.web.servlet.HandlerMapping; + +import java.util.Map; + +@Aspect +@Component +public class ProjectAuthorizeAOP { + + @Autowired + private IProjectService projectService; + @Autowired + private IProjectGroupService projectGroupService; + + @Pointcut("@annotation(cn.edu.hfut.rmdjzz.projectmanagement.annotation.ProjectAuthorize)") + public void pointcut() { + } + + @SuppressWarnings("unchecked") + @Before(value = "pointcut()") + public void preAuthorize(JoinPoint joinPoint) throws ForbiddenException { + ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + assert attributes != null; + MethodSignature signature = (MethodSignature) (joinPoint.getSignature()); + ProjectAuthorize annotation = signature.getMethod().getAnnotation(ProjectAuthorize.class); + String expression = annotation.value(); + + Integer globalAccessLevel = HttpUtils.getAttribute(attributes, TokenUtils.STAFF_GLOBAL_LEVEL); + Integer projectAccessLevel = null; + if (expression.contains("a")) { // 如果涉及到项目权限 + Integer staffId = HttpUtils.getAttribute(attributes, TokenUtils.STAFF_ID); + Map pathVariables = ((Map) (attributes + .getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST))); + assert pathVariables != null; + Integer projectId = Integer.parseInt(pathVariables.get("projectId")); + projectAccessLevel = projectGroupService.getProjectAccessLevel(staffId, globalAccessLevel, projectId); + attributes.setAttribute(TokenUtils.PROJECT_ACCESS_LEVEL, projectAccessLevel, RequestAttributes.SCOPE_REQUEST); + attributes.setAttribute(TokenUtils.TARGET_PROJECT, projectService.getById(projectId), RequestAttributes.SCOPE_REQUEST); + } + // 解析SpEL表达式 + ExpressionParser parser = new SpelExpressionParser(); + Boolean result = parser.parseExpression(expression) + .getValue(new ValidateObject(globalAccessLevel, projectAccessLevel), Boolean.class); + if (!Boolean.TRUE.equals(result)) { + throw new ForbiddenException(ForbiddenException.UNABLE_TO_OPERATE); + } + } + + private record ValidateObject(Integer g, Integer a) { + + } +} diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/exception/BadRequestException.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/exception/BadRequestException.java index cbce79b..7306a45 100644 --- a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/exception/BadRequestException.java +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/exception/BadRequestException.java @@ -4,7 +4,7 @@ package cn.edu.hfut.rmdjzz.projectmanagement.exception; * @author 张韬 * created at 2022/6/28 21:24 */ -public class BadRequestException extends Exception { +public class BadRequestException extends BusinessException { public static final String WRONG_PARAMETERS = "参数错误"; public static final String OPERATE_FAILED = "操作失败"; diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/exception/BusinessException.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/exception/BusinessException.java new file mode 100644 index 0000000..b9697a7 --- /dev/null +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/exception/BusinessException.java @@ -0,0 +1,12 @@ +package cn.edu.hfut.rmdjzz.projectmanagement.exception; + +public class BusinessException extends RuntimeException { + public BusinessException(String message) { + super(message); + } + + @Override + public synchronized Throwable fillInStackTrace() { + return this; + } +} diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/exception/ForbiddenException.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/exception/ForbiddenException.java index 7b354c7..b94b65e 100644 --- a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/exception/ForbiddenException.java +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/exception/ForbiddenException.java @@ -4,7 +4,7 @@ package cn.edu.hfut.rmdjzz.projectmanagement.exception; * @author 佘语殊 * @since 2022/7/6 20:14 */ -public class ForbiddenException extends Exception { +public class ForbiddenException extends BusinessException { public static final String UNABLE_TO_OPERATE = "无该操作权限"; diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/exception/TooManyRequestException.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/exception/TooManyRequestException.java index 8d8cefb..4f5cfae 100644 --- a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/exception/TooManyRequestException.java +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/exception/TooManyRequestException.java @@ -4,7 +4,7 @@ package cn.edu.hfut.rmdjzz.projectmanagement.exception; * @author 佘语殊 * @since 2022/7/11 17:35 */ -public class TooManyRequestException extends Exception { +public class TooManyRequestException extends BusinessException { public TooManyRequestException(String message) { super(message); } diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/exception/UnauthorizedException.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/exception/UnauthorizedException.java index c9db5df..b767987 100644 --- a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/exception/UnauthorizedException.java +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/exception/UnauthorizedException.java @@ -4,7 +4,7 @@ package cn.edu.hfut.rmdjzz.projectmanagement.exception; * @author 佘语殊 * @since 2022/7/5 23:36 */ -public class UnauthorizedException extends Exception { +public class UnauthorizedException extends BusinessException { public UnauthorizedException(String message) { super(message); } diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/interceptor/TokenInterceptor.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/interceptor/TokenInterceptor.java index 3dacef8..a68e711 100644 --- a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/interceptor/TokenInterceptor.java +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/interceptor/TokenInterceptor.java @@ -36,8 +36,6 @@ public class TokenInterceptor implements HandlerInterceptor { if (TokenUtils.checkTimeOut(token)) { throw new TokenException("Token已过期"); } -// log.debug(Objects.requireNonNull(TokenUtils.getStaffId(token))); -// log.debug(token); if (!token.equals(redisTemplate.opsForValue().get(Objects.requireNonNull(TokenUtils.getStaffId(token))))) { throw new TokenException("请重新登录"); } diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/utils/TokenUtils.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/utils/TokenUtils.java index 888c951..a9f66ad 100644 --- a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/utils/TokenUtils.java +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/utils/TokenUtils.java @@ -21,7 +21,9 @@ public final class TokenUtils { public final static String HEADER_TOKEN = "Token"; public final static String STAFF_USERNAME = "staffUsername"; public final static String STAFF_ID = "staffId"; - public final static String STAFF_GLOBAL_LEVEL = "staffGlobalLevel"; + public final static String STAFF_GLOBAL_LEVEL = "globalAccessLevel"; + public final static String PROJECT_ACCESS_LEVEL = "projectAccessLevel"; + public static final String TARGET_PROJECT = "targetProject"; private final static String DURATION = "duration"; public static String getToken(String staffUsername, Integer staffId, Integer staffGlobalLevel, Long duration) { diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/utils/http/HttpUtils.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/utils/http/HttpUtils.java index e86184a..f1dda74 100644 --- a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/utils/http/HttpUtils.java +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/utils/http/HttpUtils.java @@ -1,5 +1,8 @@ package cn.edu.hfut.rmdjzz.projectmanagement.utils.http; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.ServletRequestAttributes; + import javax.servlet.http.HttpServletRequest; import java.net.InetAddress; import java.net.UnknownHostException; @@ -52,4 +55,13 @@ public class HttpUtils { private static boolean ipAddressAvailable(String ipAddress) { return ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress); } + + @SuppressWarnings("unchecked") + public static T getAttribute(ServletRequestAttributes attributes, String key) { + Object value = attributes.getAttribute(key, RequestAttributes.SCOPE_REQUEST); + if (value == null) { + return null; + } + return (T) value; + } } diff --git a/src/test/java/cn/edu/hfut/rmdjzz/projectmanagement/UtilTests.java b/src/test/java/cn/edu/hfut/rmdjzz/projectmanagement/UtilTests.java index 02ba0d7..6dddbaa 100644 --- a/src/test/java/cn/edu/hfut/rmdjzz/projectmanagement/UtilTests.java +++ b/src/test/java/cn/edu/hfut/rmdjzz/projectmanagement/UtilTests.java @@ -3,6 +3,8 @@ package cn.edu.hfut.rmdjzz.projectmanagement; import cn.edu.hfut.rmdjzz.projectmanagement.utils.TimeUtils; import lombok.SneakyThrows; import org.junit.jupiter.api.Test; +import org.springframework.expression.ExpressionParser; +import org.springframework.expression.spel.standard.SpelExpressionParser; import java.time.LocalDate; import java.time.LocalDateTime; @@ -29,4 +31,14 @@ public class UtilTests { Class returnType = this.getClass().getMethod("timeTest").getReturnType(); System.out.println(returnType.equals(void.class)); } + + @Test + public void spelTest() { + ExpressionParser parser = new SpelExpressionParser(); + System.out.println(parser.parseExpression("a == 1").getValue(new R(2), Boolean.class)); + System.out.println(parser.parseExpression("a == 1").getValue(new R(1), Boolean.class)); + } + + record R(int a) { + } }