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 {
|
public class AopConstants {
|
||||||
private AopConstants(){}
|
private AopConstants(){}
|
||||||
public static final String HEADER_TENANT = "tenantId";
|
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_KIND = "deviceKind";
|
||||||
public static final String HEADER_DEVICE_NO = "deviceNo";
|
public static final String HEADER_DEVICE_NO = "deviceNo";
|
||||||
public static final String HEADER_APP_VERSION = "appVersion";
|
public static final String HEADER_APP_VERSION = "appVersion";
|
||||||
|
|
||||||
public static final String HEADER_SAAS_TENANT_ID = "SAAS_TENANT_ID";
|
public static final String HEADER_SAAS_TENANT_ID = "SAAS_TENANT_ID";
|
||||||
public static final String HEADER_WORKSPACE_ID = "workspaceId";
|
public static final String HEADER_WORKSPACE_ID = "workspaceId";
|
||||||
public static final String VISIT_TO = "visitTo";
|
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 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;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
public class UserInfo {
|
public class UserInfo {
|
||||||
/**
|
|
||||||
* 客户端Id
|
/**
|
||||||
*/
|
* 客户端Id
|
||||||
private String clientId;
|
*/
|
||||||
/**
|
private String clientId;
|
||||||
* 身份证
|
/**
|
||||||
*/
|
* 身份证
|
||||||
private String idCard;
|
*/
|
||||||
/**
|
private String idCard;
|
||||||
* 身份验证过期时间
|
/**
|
||||||
*/
|
* 身份验证过期时间
|
||||||
private boolean credentialsNonExpired;
|
*/
|
||||||
/**
|
private boolean credentialsNonExpired;
|
||||||
* 角色
|
/**
|
||||||
*/
|
* 角色
|
||||||
private List<String> roles;
|
*/
|
||||||
/**
|
private List<String> roles;
|
||||||
* 性别
|
/**
|
||||||
*/
|
* 性别
|
||||||
private int sex;
|
*/
|
||||||
/**
|
private int sex;
|
||||||
* 终端
|
/**
|
||||||
*/
|
* 终端
|
||||||
private String terminal;
|
*/
|
||||||
/**
|
private String terminal;
|
||||||
* axzoId
|
/**
|
||||||
*/
|
* axzoId
|
||||||
private Long userId;
|
*/
|
||||||
/**
|
private Long userId;
|
||||||
* 权限列表
|
/**
|
||||||
*/
|
* 权限列表
|
||||||
private List<String> authorities;
|
*/
|
||||||
/**
|
private List<String> authorities;
|
||||||
* 是否有效
|
/**
|
||||||
*/
|
* 是否有效
|
||||||
private boolean enabled;
|
*/
|
||||||
/**
|
private boolean enabled;
|
||||||
* 账户是否被锁定
|
/**
|
||||||
*/
|
* 账户是否被锁定
|
||||||
private boolean isLock;
|
*/
|
||||||
/**
|
private boolean isLock;
|
||||||
* 真实姓名
|
/**
|
||||||
*/
|
* 真实姓名
|
||||||
private String realName;
|
*/
|
||||||
/**
|
private String realName;
|
||||||
* 密码
|
/**
|
||||||
*/
|
* 密码
|
||||||
private String password;
|
*/
|
||||||
/**
|
private String password;
|
||||||
* 手机号
|
/**
|
||||||
*/
|
* 手机号
|
||||||
private String phoneNumber;
|
*/
|
||||||
/**
|
private String phoneNumber;
|
||||||
* id
|
/**
|
||||||
*/
|
* id
|
||||||
private Long id;
|
*/
|
||||||
private boolean accountNonLocked;
|
private Long id;
|
||||||
private String username;
|
|
||||||
|
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