完成了新的鉴权切面

master
ArgonarioD 2023-01-13 22:29:36 +08:00
parent dd681a9f20
commit 75d07779c1
10 changed files with 114 additions and 7 deletions

View File

@ -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<String, String> pathVariables = ((Map<String, String>) (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) {
}
}

View File

@ -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 = "操作失败";

View File

@ -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;
}
}

View File

@ -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 = "无该操作权限";

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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.<Integer>requireNonNull(TokenUtils.getStaffId(token))))) {
throw new TokenException("请重新登录");
}

View File

@ -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) {

View File

@ -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> T getAttribute(ServletRequestAttributes attributes, String key) {
Object value = attributes.getAttribute(key, RequestAttributes.SCOPE_REQUEST);
if (value == null) {
return null;
}
return (T) value;
}
}

View File

@ -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) {
}
}