context info
This commit is contained in:
parent
47f1bf593b
commit
e7226c1b28
@ -0,0 +1,14 @@
|
||||
package cn.axzo.framework.auth.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface PreBuildContext {
|
||||
String value() default "";
|
||||
}
|
||||
@ -1,17 +0,0 @@
|
||||
package cn.axzo.framework.auth.annotation;
|
||||
|
||||
import cn.axzo.framework.auth.domain.RequestInfo;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface PreBuildUser {
|
||||
String value() default "";
|
||||
|
||||
/**
|
||||
* RequestInfo子类Class对象
|
||||
*/
|
||||
Class<? extends RequestInfo> requestInfo() default RequestInfo.class;
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
package cn.axzo.framework.auth.config;
|
||||
|
||||
import cn.axzo.framework.auth.service.ContextInfoBuilderAspect;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class ContextInfoConfiguration {
|
||||
|
||||
@Bean
|
||||
public ContextInfoBuilderAspect ContextInfoBuilderAspect() {
|
||||
return new ContextInfoBuilderAspect();
|
||||
}
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
package cn.axzo.framework.auth.config;
|
||||
import cn.axzo.framework.auth.service.BuilderUserInfoAspect;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class UserInfoConfiguration {
|
||||
|
||||
@Bean
|
||||
public BuilderUserInfoAspect builderUserInfoAspect(){
|
||||
return new BuilderUserInfoAspect();
|
||||
}
|
||||
}
|
||||
@ -3,11 +3,14 @@ package cn.axzo.framework.auth.constants;
|
||||
public class AopConstants {
|
||||
private AopConstants(){}
|
||||
public static final String HEADER_TENANT = "tenantId";
|
||||
public static final String HEADER_SYSTEM_TYPE = "1";
|
||||
public static final String HEADER_AUTH = "authorization";
|
||||
|
||||
public static final String HEADER_SYSTEM_TYPE = "systemType";
|
||||
public static final String HEADER_SYSTEM_VERSION = "systemVersion";
|
||||
|
||||
public static final String HEADER_DEVICE_KIND = "deviceKind";
|
||||
public static final String HEADER_DEVICE_NO = "deviceNo";
|
||||
public static final String HEADER_APP_VERSION = "appVersion";
|
||||
|
||||
public static final String HEADER_SAAS_TENANT_ID = "SAAS_TENANT_ID";
|
||||
public static final String HEADER_WORKSPACE_ID = "workspaceId";
|
||||
public static final String VISIT_TO = "visitTo";
|
||||
@ -15,6 +18,7 @@ public class AopConstants {
|
||||
public static final String ENV_DEV="dev";
|
||||
|
||||
|
||||
public static final String HEADER_AUTH = "authorization";
|
||||
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,57 @@
|
||||
package cn.axzo.framework.auth.domain;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Data
|
||||
@Slf4j
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ContextInfo {
|
||||
|
||||
private String token;
|
||||
|
||||
private UserInfo userInfo;
|
||||
|
||||
private SystemAndDeviceInfo systemAndDeviceInfo;
|
||||
|
||||
private TerminalInfo terminalInfo;
|
||||
|
||||
/**
|
||||
* 项目空间id
|
||||
*/
|
||||
private Long workspaceId;
|
||||
|
||||
/**
|
||||
* 单位id
|
||||
*/
|
||||
private String ouId;
|
||||
|
||||
/**
|
||||
* 租户id
|
||||
*/
|
||||
private String tenantId;
|
||||
|
||||
/**
|
||||
* saas租户id
|
||||
*/
|
||||
private Long saasTenantId;
|
||||
|
||||
private String visitTo;
|
||||
|
||||
|
||||
public void buildCustomUserInfo(UserInfoMap userInfoMap){
|
||||
/**
|
||||
* {@link cn.axzo.apollo.server.common.config.auth.UserContextFilter.PARAMETER_PROJECTID}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
public void buildCustomInfo(HttpServletRequest request) {
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
package cn.axzo.framework.auth.domain;
|
||||
|
||||
import com.alibaba.ttl.TransmittableThreadLocal;
|
||||
|
||||
/**
|
||||
* 用户信息上下文 holder
|
||||
* @author zhangtianyu
|
||||
* @date 2022/5/11 11:21 AM
|
||||
**/
|
||||
public class ContextInfoHolder {
|
||||
private static final TransmittableThreadLocal<ContextInfo> CONTEXT = new TransmittableThreadLocal<>();
|
||||
|
||||
private ContextInfoHolder(){}
|
||||
|
||||
public static void set(ContextInfo contextInfo) {
|
||||
CONTEXT.set(contextInfo);
|
||||
}
|
||||
|
||||
public static ContextInfo get() {
|
||||
return CONTEXT.get();
|
||||
}
|
||||
|
||||
public static void clear() {
|
||||
CONTEXT.remove();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,37 +0,0 @@
|
||||
package cn.axzo.framework.auth.domain;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* 请求数据
|
||||
* @author zhangtianyu
|
||||
* @date 2022/4/25 10:10 AM
|
||||
**/
|
||||
@Data
|
||||
public class RequestInfo {
|
||||
/**
|
||||
* 租户id
|
||||
*/
|
||||
private String tenantId;
|
||||
/**
|
||||
* saas租户id
|
||||
*/
|
||||
private Long saasTenantId;
|
||||
private String systemType;
|
||||
private String deviceKind;
|
||||
private String deviceNo;
|
||||
private String appVersion;
|
||||
private String token;
|
||||
private String visitTo;
|
||||
/**
|
||||
* 项目空间id
|
||||
*/
|
||||
private Long workspaceId;
|
||||
/**
|
||||
* 使用http request 设置自定义字段
|
||||
* @param request http请求
|
||||
*/
|
||||
public void buildCustomRequestInfo(HttpServletRequest request) {}
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package cn.axzo.framework.auth.domain;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
**/
|
||||
@Data
|
||||
public class SystemAndDeviceInfo {
|
||||
|
||||
private String systemType;
|
||||
private String deviceKind;
|
||||
private String deviceNo;
|
||||
private String appVersion;
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package cn.axzo.framework.auth.domain;
|
||||
|
||||
public class TerminalInfo {
|
||||
|
||||
|
||||
private String terminal;
|
||||
|
||||
CMS = NT_CMS, (1, cms)
|
||||
|
||||
|
||||
boolean isCMS() {
|
||||
if("1".equals(terminal)) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -7,83 +7,71 @@ import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@Data
|
||||
@Slf4j
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class UserInfo {
|
||||
/**
|
||||
* 客户端Id
|
||||
*/
|
||||
private String clientId;
|
||||
/**
|
||||
* 身份证
|
||||
*/
|
||||
private String idCard;
|
||||
/**
|
||||
* 身份验证过期时间
|
||||
*/
|
||||
private boolean credentialsNonExpired;
|
||||
/**
|
||||
* 角色
|
||||
*/
|
||||
private List<String> roles;
|
||||
/**
|
||||
* 性别
|
||||
*/
|
||||
private int sex;
|
||||
/**
|
||||
* 终端
|
||||
*/
|
||||
private String terminal;
|
||||
/**
|
||||
* axzoId
|
||||
*/
|
||||
private Long userId;
|
||||
/**
|
||||
* 权限列表
|
||||
*/
|
||||
private List<String> authorities;
|
||||
/**
|
||||
* 是否有效
|
||||
*/
|
||||
private boolean enabled;
|
||||
/**
|
||||
* 账户是否被锁定
|
||||
*/
|
||||
private boolean isLock;
|
||||
/**
|
||||
* 真实姓名
|
||||
*/
|
||||
private String realName;
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
private String password;
|
||||
/**
|
||||
* 手机号
|
||||
*/
|
||||
private String phoneNumber;
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
private Long id;
|
||||
private boolean accountNonLocked;
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* 客户端Id
|
||||
*/
|
||||
private String clientId;
|
||||
/**
|
||||
* 身份证
|
||||
*/
|
||||
private String idCard;
|
||||
/**
|
||||
* 身份验证过期时间
|
||||
*/
|
||||
private boolean credentialsNonExpired;
|
||||
/**
|
||||
* 角色
|
||||
*/
|
||||
private List<String> roles;
|
||||
/**
|
||||
* 性别
|
||||
*/
|
||||
private int sex;
|
||||
/**
|
||||
* 终端
|
||||
*/
|
||||
private String terminal;
|
||||
/**
|
||||
* axzoId
|
||||
*/
|
||||
private Long userId;
|
||||
/**
|
||||
* 权限列表
|
||||
*/
|
||||
private List<String> authorities;
|
||||
/**
|
||||
* 是否有效
|
||||
*/
|
||||
private boolean enabled;
|
||||
/**
|
||||
* 账户是否被锁定
|
||||
*/
|
||||
private boolean isLock;
|
||||
/**
|
||||
* 真实姓名
|
||||
*/
|
||||
private String realName;
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
private String password;
|
||||
/**
|
||||
* 手机号
|
||||
*/
|
||||
private String phoneNumber;
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
private boolean accountNonLocked;
|
||||
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* 请求信息
|
||||
*/
|
||||
private RequestInfo requestInfo;
|
||||
|
||||
/**
|
||||
* 使用用户信息map 设置自定义字段
|
||||
* @param userInfoMap 用户信息
|
||||
*/
|
||||
public void buildCustomUserInfo(UserInfoMap userInfoMap){}
|
||||
|
||||
public <T extends RequestInfo> T getRequestInfo() {
|
||||
return (T) requestInfo;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,27 +0,0 @@
|
||||
package cn.axzo.framework.auth.domain;
|
||||
|
||||
import com.alibaba.ttl.TransmittableThreadLocal;
|
||||
|
||||
/**
|
||||
* 用户信息上下文 holder
|
||||
* @author zhangtianyu
|
||||
* @date 2022/5/11 11:21 AM
|
||||
**/
|
||||
public class UserInfoHolder {
|
||||
private static final TransmittableThreadLocal<UserInfo> CONTEXT = new TransmittableThreadLocal<>();
|
||||
|
||||
private UserInfoHolder(){}
|
||||
|
||||
public static void set(UserInfo userInfo) {
|
||||
CONTEXT.set(userInfo);
|
||||
}
|
||||
|
||||
public static UserInfo get() {
|
||||
return CONTEXT.get();
|
||||
}
|
||||
|
||||
public static void clear() {
|
||||
CONTEXT.remove();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,173 +0,0 @@
|
||||
package cn.axzo.framework.auth.service;
|
||||
|
||||
import cn.axzo.framework.auth.AuthException;
|
||||
import cn.axzo.framework.auth.annotation.PreBuildUser;
|
||||
import cn.axzo.framework.auth.constants.AopConstants;
|
||||
import cn.axzo.framework.auth.domain.RequestInfo;
|
||||
import cn.axzo.framework.auth.domain.UserInfo;
|
||||
import cn.axzo.framework.auth.domain.UserInfoHolder;
|
||||
import cn.axzo.framework.auth.enums.EnvEnum;
|
||||
import cn.azxo.framework.common.logger.logback.PodNamespacePropertyDefiner;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.codec.Base64;
|
||||
import cn.hutool.core.text.CharSequenceUtil;
|
||||
import cn.hutool.http.HttpException;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.axzo.framework.auth.domain.UserInfoMap;
|
||||
import cn.hutool.core.lang.TypeReference;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
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.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
|
||||
@Slf4j
|
||||
@Aspect
|
||||
@Component
|
||||
@Order(1)
|
||||
public class BuilderUserInfoAspect {
|
||||
|
||||
@Around(value = "@within(preBuildUser)")
|
||||
public Object classHandler(ProceedingJoinPoint pjp, PreBuildUser preBuildUser) {
|
||||
return handle(pjp, preBuildUser);
|
||||
}
|
||||
|
||||
@Around(value = "@annotation(preBuildUser)")
|
||||
public Object methodHandler(ProceedingJoinPoint pjp, PreBuildUser preBuildUser) {
|
||||
return handle(pjp, preBuildUser);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public Object handle(ProceedingJoinPoint pjp, PreBuildUser preBuildUser) {
|
||||
HttpServletRequest httpRequest = null;
|
||||
try {
|
||||
//获取request
|
||||
httpRequest = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
|
||||
} catch (Exception exception) {
|
||||
log.error("can not get request,there is a error occurrence ==>" + exception.getCause().getMessage());
|
||||
}
|
||||
AuthException.error(Objects.nonNull(httpRequest), "httpRequest cant be null, this is error");
|
||||
|
||||
fillInUserInfoDetail(httpRequest, pjp, preBuildUser.requestInfo());
|
||||
try {
|
||||
return pjp.proceed();
|
||||
} finally {
|
||||
UserInfoHolder.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void fillInUserInfoDetail(HttpServletRequest request, ProceedingJoinPoint pjp, Class<? extends RequestInfo> requestInfoClass) {
|
||||
String userinfoJson;
|
||||
// 本地运行 分两种情况 postMan/junit
|
||||
// 判断本地环境
|
||||
if (getSystemProperties() == null) {
|
||||
// 如果本地环境 有两种如果是postman类型调用手动调用pudge
|
||||
String token = request.getHeader("Authorization");
|
||||
if (CharSequenceUtil.isEmpty(token)) {
|
||||
// 硬逻辑 如果不携带token 可理解为junit测试 这里不覆盖 Userinfo的信息
|
||||
return;
|
||||
}
|
||||
userinfoJson = getUserInfoFromToken(token);
|
||||
} else {
|
||||
// 走 apisix 获取的请求
|
||||
String userJsonInfo = request.getHeader(AopConstants.USER_INFO);
|
||||
AuthException.error(CharSequenceUtil.isNotEmpty(userJsonInfo), "do not have userinfo error , please check apisix config is correct");
|
||||
// 转编码
|
||||
userinfoJson = Base64.decodeStr(userJsonInfo);
|
||||
|
||||
}
|
||||
|
||||
MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
|
||||
Method method = methodSignature.getMethod();
|
||||
Class<?>[] parameterTypes = method.getParameterTypes();
|
||||
Object[] pjpArgs = pjp.getArgs();
|
||||
UserInfo userInfo = new UserInfo();
|
||||
for (int i = 0; i < parameterTypes.length; i++) {
|
||||
if (parameterTypes[i].isAssignableFrom(UserInfo.class)) {
|
||||
userInfo = (UserInfo) pjpArgs[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
buildRequestInfo(userInfo, request, requestInfoClass);
|
||||
buildUserInfo(userInfo, userinfoJson);
|
||||
UserInfoHolder.set(userInfo);
|
||||
}
|
||||
|
||||
public String getUserInfoFromToken(String token) {
|
||||
// postman调用
|
||||
String customerEnv = getCustomerEnv();
|
||||
customerEnv = CharSequenceUtil.isEmpty(customerEnv) ? AopConstants.ENV_DEV : customerEnv;
|
||||
String url = EnvEnum.getValueByKey(customerEnv);
|
||||
AuthException.error(CharSequenceUtil.isNotEmpty(url), "There is no correct path to request");
|
||||
|
||||
try {
|
||||
String response = HttpRequest.get(url).header("Authorization", token).execute().body();
|
||||
// 使用token获取用户信息
|
||||
AuthException.error(CharSequenceUtil.isNotEmpty(response), "not find user by token from pudge");
|
||||
return response;
|
||||
} catch (HttpException e) {
|
||||
throw new AuthException("call pudge get/user error.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从env/properties 获取my_pod_namespace 的value
|
||||
*/
|
||||
public String getSystemProperties() {
|
||||
PodNamespacePropertyDefiner podNamespacePropertyDefiner = new PodNamespacePropertyDefiner();
|
||||
return podNamespacePropertyDefiner.getPropertyValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* 从本地拿 CUSTOM_ENV的值
|
||||
*/
|
||||
public String getCustomerEnv() {
|
||||
PodNamespacePropertyDefiner podNamespacePropertyDefiner = new PodNamespacePropertyDefiner();
|
||||
return (String) podNamespacePropertyDefiner.getSystemProperties().get("CUSTOM_ENV");
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
private void buildRequestInfo(UserInfo userInfo, HttpServletRequest request, Class<? extends RequestInfo> requestInfoClass) {
|
||||
RequestInfo requestInfo = userInfo.getRequestInfo();
|
||||
if (Objects.isNull(requestInfo)) {
|
||||
requestInfo = requestInfoClass.newInstance();
|
||||
userInfo.setRequestInfo(requestInfo);
|
||||
}
|
||||
// 请求头获取数据
|
||||
requestInfo.setAppVersion(request.getHeader(AopConstants.HEADER_APP_VERSION));
|
||||
requestInfo.setDeviceKind(request.getHeader(AopConstants.HEADER_DEVICE_KIND));
|
||||
requestInfo.setDeviceNo(request.getHeader(AopConstants.HEADER_DEVICE_NO));
|
||||
requestInfo.setSystemType(request.getHeader(AopConstants.HEADER_SYSTEM_TYPE));
|
||||
requestInfo.setTenantId(request.getHeader(AopConstants.HEADER_TENANT));
|
||||
requestInfo.setVisitTo(request.getHeader(AopConstants.VISIT_TO));
|
||||
requestInfo.setToken(request.getHeader(AopConstants.HEADER_AUTH));
|
||||
String saasTenantId = request.getHeader(AopConstants.HEADER_SAAS_TENANT_ID);
|
||||
requestInfo.setSaasTenantId(CharSequenceUtil.isEmpty(saasTenantId) ? null : Long.valueOf(saasTenantId));
|
||||
String workspaceId = request.getHeader(AopConstants.HEADER_WORKSPACE_ID);
|
||||
requestInfo.setWorkspaceId(CharSequenceUtil.isEmpty(workspaceId) ? null : Long.valueOf(workspaceId));
|
||||
requestInfo.buildCustomRequestInfo(request);
|
||||
}
|
||||
|
||||
public void buildUserInfo(UserInfo userInfo, String userJsonInfo) {
|
||||
TypeReference<Map<String, Object>> mapTypeReference = new TypeReference<Map<String, Object>>(){};
|
||||
Map<String, Object> map = JSONUtil.toBean(userJsonInfo, mapTypeReference, false);
|
||||
// 对bean进行封装属性
|
||||
BeanUtil.fillBeanWithMap(map, userInfo, false);
|
||||
|
||||
userInfo.buildCustomUserInfo(new UserInfoMap(map));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,180 @@
|
||||
package cn.axzo.framework.auth.service;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
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.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import cn.axzo.framework.auth.AuthException;
|
||||
import cn.axzo.framework.auth.annotation.PreBuildContext;
|
||||
import cn.axzo.framework.auth.constants.AopConstants;
|
||||
import cn.axzo.framework.auth.domain.ContextInfo;
|
||||
import cn.axzo.framework.auth.domain.ContextInfoHolder;
|
||||
import cn.axzo.framework.auth.domain.SystemAndDeviceInfo;
|
||||
import cn.axzo.framework.auth.domain.UserInfo;
|
||||
import cn.axzo.framework.auth.domain.UserInfoMap;
|
||||
import cn.axzo.framework.auth.enums.EnvEnum;
|
||||
import cn.azxo.framework.common.logger.logback.PodNamespacePropertyDefiner;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.codec.Base64;
|
||||
import cn.hutool.core.lang.TypeReference;
|
||||
import cn.hutool.core.text.CharSequenceUtil;
|
||||
import cn.hutool.http.HttpException;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@Aspect
|
||||
@Component
|
||||
@Order(1)
|
||||
public class ContextInfoBuilderAspect {
|
||||
|
||||
@Around(value = "@within(preBuildContext)")
|
||||
public Object classHandler(ProceedingJoinPoint pjp, PreBuildContext preBuildContext) {
|
||||
return handle(pjp, preBuildContext);
|
||||
}
|
||||
|
||||
@Around(value = "@annotation(preBuildContext)")
|
||||
public Object methodHandler(ProceedingJoinPoint pjp, PreBuildContext preBuildContext) {
|
||||
return handle(pjp, preBuildContext);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public Object handle(ProceedingJoinPoint pjp, PreBuildContext preBuildContext) {
|
||||
HttpServletRequest httpRequest = null;
|
||||
try {
|
||||
// 获取request
|
||||
httpRequest = ((ServletRequestAttributes) Objects
|
||||
.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
|
||||
} catch (Exception exception) {
|
||||
log.error("can not get request,there is a error occurrence ==>" + exception.getCause().getMessage());
|
||||
}
|
||||
AuthException.error(Objects.nonNull(httpRequest), "httpRequest cant be null, this is error");
|
||||
|
||||
fillInContextInfoDetail(httpRequest, pjp);
|
||||
try {
|
||||
return pjp.proceed();
|
||||
} finally {
|
||||
ContextInfoHolder.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void fillInContextInfoDetail(HttpServletRequest request, ProceedingJoinPoint pjp) {
|
||||
String userinfoJson;
|
||||
// 本地运行 分两种情况 postMan/junit
|
||||
// 判断本地环境
|
||||
if (getSystemProperties() == null) {
|
||||
// 如果本地环境 有两种如果是postman类型调用手动调用pudge
|
||||
String token = request.getHeader("Authorization");
|
||||
if (CharSequenceUtil.isEmpty(token)) {
|
||||
// 硬逻辑 如果不携带token 可理解为junit测试 这里不覆盖 Userinfo的信息
|
||||
return;
|
||||
}
|
||||
userinfoJson = getUserInfoFromToken(token);
|
||||
} else {
|
||||
// 走 apisix 获取的请求
|
||||
String userJsonInfo = request.getHeader(AopConstants.USER_INFO);
|
||||
AuthException.error(CharSequenceUtil.isNotEmpty(userJsonInfo),
|
||||
"do not have userinfo error , please check apisix config is correct");
|
||||
// 转编码
|
||||
userinfoJson = Base64.decodeStr(userJsonInfo);
|
||||
}
|
||||
|
||||
ContextInfo contextInfo = new ContextInfo();
|
||||
buildUserInfo(contextInfo, userinfoJson);
|
||||
fillContextInfoWithRequest(contextInfo, request);
|
||||
contextInfo.buildCustomInfo(request);
|
||||
ContextInfoHolder.set(contextInfo);
|
||||
|
||||
MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
|
||||
Method method = methodSignature.getMethod();
|
||||
Class<?>[] parameterTypes = method.getParameterTypes();
|
||||
Object[] pjpArgs = pjp.getArgs();
|
||||
for (int i = 0; i < parameterTypes.length; i++) {
|
||||
if (parameterTypes[i].isAssignableFrom(ContextInfo.class)) {
|
||||
contextInfo = (ContextInfo) pjpArgs[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public String getUserInfoFromToken(String token) {
|
||||
// postman调用
|
||||
String customerEnv = getCustomerEnv();
|
||||
customerEnv = CharSequenceUtil.isEmpty(customerEnv) ? AopConstants.ENV_DEV : customerEnv;
|
||||
String url = EnvEnum.getValueByKey(customerEnv);
|
||||
AuthException.error(CharSequenceUtil.isNotEmpty(url), "There is no correct path to request");
|
||||
|
||||
try {
|
||||
String response = HttpRequest.get(url).header("Authorization", token).execute().body();
|
||||
// 使用token获取用户信息
|
||||
AuthException.error(CharSequenceUtil.isNotEmpty(response), "not find user by token from pudge");
|
||||
return response;
|
||||
} catch (HttpException e) {
|
||||
throw new AuthException("call pudge get/user error.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从env/properties 获取my_pod_namespace 的value
|
||||
*/
|
||||
public String getSystemProperties() {
|
||||
PodNamespacePropertyDefiner podNamespacePropertyDefiner = new PodNamespacePropertyDefiner();
|
||||
return podNamespacePropertyDefiner.getPropertyValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* 从本地拿 CUSTOM_ENV的值
|
||||
*/
|
||||
public String getCustomerEnv() {
|
||||
PodNamespacePropertyDefiner podNamespacePropertyDefiner = new PodNamespacePropertyDefiner();
|
||||
return (String) podNamespacePropertyDefiner.getSystemProperties().get("CUSTOM_ENV");
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
private void fillContextInfoWithRequest(ContextInfo contextInfo, HttpServletRequest request) {
|
||||
|
||||
SystemAndDeviceInfo sdInfo = new SystemAndDeviceInfo();
|
||||
// 请求头获取数据
|
||||
sdInfo.setAppVersion(request.getHeader(AopConstants.HEADER_APP_VERSION));
|
||||
sdInfo.setDeviceKind(request.getHeader(AopConstants.HEADER_DEVICE_KIND));
|
||||
sdInfo.setDeviceNo(request.getHeader(AopConstants.HEADER_DEVICE_NO));
|
||||
sdInfo.setSystemType(request.getHeader(AopConstants.HEADER_SYSTEM_TYPE));
|
||||
|
||||
contextInfo.setSystemAndDeviceInfo(sdInfo);
|
||||
|
||||
contextInfo.setTenantId(request.getHeader(AopConstants.HEADER_TENANT));
|
||||
contextInfo.setVisitTo(request.getHeader(AopConstants.VISIT_TO));
|
||||
contextInfo.setToken(request.getHeader(AopConstants.HEADER_AUTH));
|
||||
String saasTenantId = request.getHeader(AopConstants.HEADER_SAAS_TENANT_ID);
|
||||
contextInfo.setSaasTenantId(CharSequenceUtil.isEmpty(saasTenantId) ? null : Long.valueOf(saasTenantId));
|
||||
String workspaceId = request.getHeader(AopConstants.HEADER_WORKSPACE_ID);
|
||||
contextInfo.setWorkspaceId(CharSequenceUtil.isEmpty(workspaceId) ? null : Long.valueOf(workspaceId));
|
||||
}
|
||||
|
||||
public void buildUserInfo(ContextInfo contextInfo, String userJsonInfo) {
|
||||
UserInfo userInfo = new UserInfo();
|
||||
TypeReference<Map<String, Object>> mapTypeReference = new TypeReference<Map<String, Object>>() {
|
||||
};
|
||||
Map<String, Object> map = JSONUtil.toBean(userJsonInfo, mapTypeReference, false);
|
||||
// 对bean进行封装属性
|
||||
BeanUtil.fillBeanWithMap(map, userInfo, false);
|
||||
|
||||
contextInfo.setUserInfo(userInfo);
|
||||
contextInfo.buildCustomUserInfo(new UserInfoMap(map));
|
||||
}
|
||||
|
||||
}
|
||||
@ -1 +1 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=cn.axzo.framework.auth.config.UserInfoConfiguration
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=cn.axzo.framework.auth.config.ContextInfoConfiguration
|
||||
Loading…
Reference in New Issue
Block a user