diff --git a/src/main/java/com/easysoftware/adapter/query/ApplicationVersionQueryAdapter.java b/src/main/java/com/easysoftware/adapter/query/ApplicationVersionQueryAdapter.java index b378670c49c23d0503a44f9e2d38736b7a82906a..70649775d4e70cabc473ba4b3fabcdbe41793d13 100644 --- a/src/main/java/com/easysoftware/adapter/query/ApplicationVersionQueryAdapter.java +++ b/src/main/java/com/easysoftware/adapter/query/ApplicationVersionQueryAdapter.java @@ -11,6 +11,8 @@ package com.easysoftware.adapter.query; +import com.easysoftware.common.account.UerPermissionDef; +import com.easysoftware.common.annotation.PreUserPermission; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; @@ -21,7 +23,6 @@ import com.easysoftware.application.applicationversion.dto.ApplicationColumnSear import com.easysoftware.application.applicationversion.dto.ApplicationVersionSearchCondition; import com.easysoftware.common.aop.RequestLimitRedis; -import cn.dev33.satoken.stp.StpUtil; import jakarta.validation.Valid; @RestController @@ -42,9 +43,9 @@ public class ApplicationVersionQueryAdapter { */ @GetMapping() @RequestLimitRedis() + @PreUserPermission(UerPermissionDef.USER_PERMISSION_READ) public ResponseEntity searchAppVersion(@Valid final ApplicationVersionSearchCondition condition) { // 检查会话权限 - StpUtil.checkPermission("easysoftwareread"); return appVersionService.searchAppVersion(condition); } @@ -57,9 +58,9 @@ public class ApplicationVersionQueryAdapter { */ @GetMapping("/column") @RequestLimitRedis() + @PreUserPermission(UerPermissionDef.USER_PERMISSION_READ) public ResponseEntity searchAppVerColumn(@Valid final ApplicationColumnSearchCondition condition) { // 检查会话权限 - StpUtil.checkPermission("easysoftwareread"); return appVersionService.searchAppVerColumn(condition); } } diff --git a/src/main/java/com/easysoftware/common/account/UerPermissionDef.java b/src/main/java/com/easysoftware/common/account/UerPermissionDef.java new file mode 100644 index 0000000000000000000000000000000000000000..db81a11a8a5f97756d5a47090da036a1741f60d5 --- /dev/null +++ b/src/main/java/com/easysoftware/common/account/UerPermissionDef.java @@ -0,0 +1,12 @@ +package com.easysoftware.common.account; + +public final class UerPermissionDef { + /** + * user permission - easysoftwareread. + */ + public static final String USER_PERMISSION_READ = "easysoftwareread"; + + private UerPermissionDef() { + throw new RuntimeException("Not supported for instantiation"); + } +} diff --git a/src/main/java/com/easysoftware/common/account/UserPermission.java b/src/main/java/com/easysoftware/common/account/UserPermission.java new file mode 100644 index 0000000000000000000000000000000000000000..1215a4677b7c8dc92740513d243f15bf225dc213 --- /dev/null +++ b/src/main/java/com/easysoftware/common/account/UserPermission.java @@ -0,0 +1,157 @@ +package com.easysoftware.common.account; + +import cn.dev33.satoken.exception.NotLoginException; +import com.easysoftware.common.constant.HttpConstant; +import com.easysoftware.common.exception.HttpRequestException; +import com.easysoftware.common.utils.HttpClientUtil; +import com.easysoftware.common.utils.ObjectMapperUtil; +import com.fasterxml.jackson.databind.JsonNode; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Objects; +import java.util.Optional; + +@Component +public class UserPermission { + + /** + * Logger for UserPermission. + */ + private static final Logger LOGGER = LoggerFactory.getLogger(UserPermission.class); + + /** + * Value injected for the manage token API. + */ + @Value("${oneid.manage.tokenApi}") + private String manageTokenApi; + + /** + * Value injected for the manage API body. + */ + @Value("${oneid.manage.apiBody}") + private String manageApiBody; + + /** + * Value injected for the permission API. + */ + @Value("${oneid.permissionApi}") + private String permissionApi; + + /** + * Value injected for the cookie token name. + */ + @Value("${cookie.token.name}") + private String cookieTokenName; + + /** + * Get user permission by user token and manage token. + * @return Collection of user permissions. + */ + public HashSet getPermissionList() { + // 使用获取userToken + String userToken = getUserToken(); + + // 获取oneid manage token + String manageToken = getManageToken(); + + // 使用userToke、manageToken查询用户权限 + Cookie cookie = getCookie(cookieTokenName); + String response = HttpClientUtil.getHttpClient(permissionApi, manageToken, userToken, cookie.getValue()); + JsonNode resJson = ObjectMapperUtil.toJsonNode(response); + + String resCode = resJson.get("code").asText(); + // 查询权限失败 + if (!"200".equals(resCode)) { + LOGGER.error("query user permissions failed"); + throw new HttpRequestException("query user permissions failed"); + } + + // 空权限账户 + if (!resJson.has("data")) { + return new HashSet(); + } + + // 设置权限 + JsonNode permissions = resJson.get("data").get("permissions"); + HashSet permissionSet = new HashSet<>(); + for (JsonNode per : permissions) { + permissionSet.add(per.asText()); + } + + return permissionSet; + } + + /** + * Get manage token. + * @return manage token. + */ + private String getManageToken() { + String response = HttpClientUtil.postHttpClient(manageTokenApi, manageApiBody); + JsonNode resJson = ObjectMapperUtil.toJsonNode(response); + return resJson.get("token").asText(); + } + + /** + * Get user token. + * @return user token. + */ + private String getUserToken() { + ServletRequestAttributes servletRequestAttributes = + (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + if (Objects.isNull(servletRequestAttributes)) { + LOGGER.error("Missing HTTP parameter"); + throw new HttpRequestException("Missing HTTP parameter"); + } + HttpServletRequest httpServletRequest = servletRequestAttributes.getRequest(); + + String userToken = httpServletRequest.getHeader(HttpConstant.TOKEN); + if (null == userToken) { + LOGGER.error("Missing user token"); + throw new NotLoginException("user token expired or no login", "", ""); + } + + return userToken; + } + + /** + * Get a cookie from the HttpServletRequest. + * + * @param cookieName The name of the cookie to be obtained. + * @return cookie . + */ + private Cookie getCookie(String cookieName) { + ServletRequestAttributes servletRequestAttributes = + (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + if (Objects.isNull(servletRequestAttributes)) { + LOGGER.error("Missing HTTP parameter"); + throw new HttpRequestException("Missing HTTP parameter"); + } + + Cookie[] cookies = servletRequestAttributes.getRequest().getCookies(); + Cookie cookie = null; + if (null != cookies) { + // 获取cookie中的token + Optional first = Arrays.stream(cookies).filter(c -> cookieName.equals(c.getName())) + .findFirst(); + if (first.isPresent()) { + cookie = first.get(); + } + } + + if (null == cookie) { + LOGGER.error("Missing valid cookies"); + throw new NotLoginException("user token expired or no login", "", ""); + } + return cookie; + } + +} diff --git a/src/main/java/com/easysoftware/common/annotation/PreUserPermission.java b/src/main/java/com/easysoftware/common/annotation/PreUserPermission.java new file mode 100644 index 0000000000000000000000000000000000000000..aa56c28ab865faf72e627413587a00fff7586e46 --- /dev/null +++ b/src/main/java/com/easysoftware/common/annotation/PreUserPermission.java @@ -0,0 +1,25 @@ +package com.easysoftware.common.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.annotation.Retention; +import java.lang.annotation.Inherited; +import java.lang.annotation.Documented; + +/** + * This annotation is used for authentication. + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Inherited +@Documented +public @interface PreUserPermission { + + /** + * Specifies the number of allowed requests (default value: 5). + * + * @return Default to empty. + */ + String[] value() default {}; +} diff --git a/src/main/java/com/easysoftware/common/aop/PreUserPermissionAspect.java b/src/main/java/com/easysoftware/common/aop/PreUserPermissionAspect.java new file mode 100644 index 0000000000000000000000000000000000000000..772df0aab58879ddc85f082b9bf8c318981335df --- /dev/null +++ b/src/main/java/com/easysoftware/common/aop/PreUserPermissionAspect.java @@ -0,0 +1,69 @@ +package com.easysoftware.common.aop; + +import com.easysoftware.common.account.UserPermission; +import com.easysoftware.common.annotation.PreUserPermission; +import com.easysoftware.common.utils.ResultUtil; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Component; + +import java.lang.reflect.Method; +import java.util.HashSet; +import java.util.Objects; + +@Aspect +@Component +public class PreUserPermissionAspect { + + /** + * Autowired UserPermission for get user permission. + */ + @Autowired + private UserPermission userPermission; + + /** + * Advice method called before a method with PreUserPermission, and authentication. + * @param joinPoint The JoinPoint representing the intercepted method. + * @throws Throwable if an error occurs during method execution, or authentication fail. + * @return Business processing results. + */ + @Around("@annotation(com.easysoftware.common.annotation.PreUserPermission)") + public Object around(final ProceedingJoinPoint joinPoint) throws Throwable { + /* 用户权限检查 */ + try { + /* 获取PreUserPermission注解参数 */ + MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); + Method method = methodSignature.getMethod(); + PreUserPermission preUserPermission = method.getAnnotation(PreUserPermission.class); + String[] paramValues = preUserPermission.value(); + + /* 方法使用注解,如果未指定参数,默认无权限控制;否则,进行权限检查 */ + if (!Objects.isNull(paramValues) && 0 != paramValues.length) { + /* 获取客户权限 */ + HashSet permissionSet = userPermission.getPermissionList(); + + /* 检查客户权限是否满足访问权限 */ + boolean permissionFlag = false; + for (String item : paramValues) { + if (permissionSet.contains(item)) { + permissionFlag = true; + break; + } + } + + if (!permissionFlag) { + return ResultUtil.fail(HttpStatus.UNAUTHORIZED, "用户无此权限"); + } + } + } catch (Exception e) { + return ResultUtil.fail(HttpStatus.UNAUTHORIZED, "用户鉴权失败"); + } + + /* 业务处理 */ + return joinPoint.proceed(); + } +}