Merge branch 'new_3A' of axzsource.com:shanghai/axzo-framework into new_3A

This commit is contained in:
liang 2022-06-14 15:47:49 +08:00
commit f23b14aa32
6 changed files with 205 additions and 28 deletions

View File

@ -18,6 +18,7 @@
<maven.compiler.source>8</maven.compiler.source> <maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target> <maven.compiler.target>8</maven.compiler.target>
<javax.servlet.version>4.0.1</javax.servlet.version> <javax.servlet.version>4.0.1</javax.servlet.version>
<sa-token.version>1.30.0</sa-token.version>
</properties> </properties>
<dependencies> <dependencies>
@ -91,6 +92,12 @@
<artifactId>transmittable-thread-local</artifactId> <artifactId>transmittable-thread-local</artifactId>
<version>2.12.6</version> <version>2.12.6</version>
</dependency> </dependency>
<!-- Sa-Token 权限认证, 在线文档http://sa-token.dev33.cn/ -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
<version>${sa-token.version}</version>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -6,10 +6,13 @@ package cn.axzo.framework.auth;
* @date 2022/5/11 3:39 PM * @date 2022/5/11 3:39 PM
**/ **/
public class AuthException extends RuntimeException { public class AuthException extends RuntimeException {
public AuthException(String msg) { public AuthException(String msg, Exception e) {
super(msg); super(msg, e);
} }
public AuthException(String msg) {
super(msg);
}
public static void error(boolean condition, String msg) { public static void error(boolean condition, String msg) {
if (!condition) { if (!condition) {
throw new AuthException(msg); throw new AuthException(msg);

View File

@ -1,9 +1,10 @@
package cn.axzo.framework.auth.config; package cn.axzo.framework.auth.config;
import cn.axzo.framework.auth.service.ContextInfoBuilderAspect;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import cn.axzo.framework.auth.service.ContextInfoBuilderAspect;
@Configuration @Configuration
public class ContextInfoConfiguration { public class ContextInfoConfiguration {

View File

@ -1,9 +1,19 @@
package cn.axzo.framework.auth.domain; package cn.axzo.framework.auth.domain;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
public class TerminalInfo { public class TerminalInfo {
/**
* TODO: 数据库迁移terminal字符串有存到数据库里的比如这个函数
*
* {@link cn.axzo.pudge.webapi.modules.panel.PanelCommonController.getBannerFromSmp(Long)}
*
*/
/** /**
* 之前的CEMSPMS合成一个叫CMS了 * 之前的CEMSPMS合成一个叫CMS了
@ -30,11 +40,11 @@ public class TerminalInfo {
public static final String STR_TERMINAL_CMS = "cms"; public static final String STR_TERMINAL_CMS = "cms";
@Deprecated @Deprecated
public static final String NUM_TERMINAL_CMS = "3"; public static final String NUM_TERMINAL_CMS = "3";
//调试的时候发现有一个15是CMS // 调试的时候发现有一个15是CMS
@Deprecated @Deprecated
public static final String NUM15_TERMINAL_CMS = "15"; public static final String NUM15_TERMINAL_CMS = "15";
/** /**
* 从业人员App企业版App * 从业人员App企业版App
*/ */
@ -81,10 +91,32 @@ public class TerminalInfo {
@Deprecated @Deprecated
public static final String STR_TERMINAL_PROJ = "proj"; public static final String STR_TERMINAL_PROJ = "proj";
/**
* 智能面板
*/
@Deprecated
public static final String STR_TERMINAL_SM = "sm";
/**
* 智能面板
*/
@Deprecated
public static final String STR_TERMINAL_SMP = "smp";
@Deprecated @Deprecated
public static final String STR_TERMINAL_SCREEN = "screen"; public static final String STR_TERMINAL_SCREEN = "screen";
private static Map<String, String> aliasMap = new HashMap<String, String>(); /**
* cn.axzo.pudge.server.modules.sys.enums.AppTerminalTypeEnum
*
* 智能面板插件
*/
@Deprecated
public static final String STR_TERMINAL_PL_PREFIX = "pl-";
private static Map<String, String> aliasMap = new HashMap<>();
private static Map<String, List<String>> ntLegacyMap = new HashMap<>();
/** /**
* 企业工作台Web-总包 * 企业工作台Web-总包
@ -106,6 +138,9 @@ public class TerminalInfo {
aliasMap.put(NUM_TERMINAL_CMS, NT_CMS_WEB_PROJ); aliasMap.put(NUM_TERMINAL_CMS, NT_CMS_WEB_PROJ);
aliasMap.put(NUM15_TERMINAL_CMS, NT_CMS_WEB_PROJ); aliasMap.put(NUM15_TERMINAL_CMS, NT_CMS_WEB_PROJ);
// 实际上不应该是直接对应于PROJ默认先对应一个需要再guess一下 // 实际上不应该是直接对应于PROJ默认先对应一个需要再guess一下
aliasMap.put(STR_TERMINAL_PMS, NT_CMS_WEB_PROJ);
aliasMap.put(NUM_TERMINAL_PMS, NT_CMS_WEB_PROJ);
} }
/** /**
@ -114,6 +149,8 @@ public class TerminalInfo {
public static final String NT_CMP_APP_ENT_ZB = "NT_CMP_APP_ENT_ZB"; public static final String NT_CMP_APP_ENT_ZB = "NT_CMP_APP_ENT_ZB";
static { static {
aliasMap.put(NT_CMP_APP_ENT_ZB, NT_CMP_APP_ENT_ZB); aliasMap.put(NT_CMP_APP_ENT_ZB, NT_CMP_APP_ENT_ZB);
aliasMap.put(STR_TERMINAL_CEMS, NT_CMS_WEB_PROJ);
aliasMap.put(NUM_TERMINAL_CEMS, NT_CMS_WEB_PROJ);
} }
/** /**
@ -135,6 +172,7 @@ public class TerminalInfo {
aliasMap.put(NT_CM_APP_CM_LEADER, NT_CM_APP_CM_LEADER); aliasMap.put(NT_CM_APP_CM_LEADER, NT_CM_APP_CM_LEADER);
aliasMap.put(STR_TERMINAL_CM_LEADER, NT_CM_APP_CM_LEADER); aliasMap.put(STR_TERMINAL_CM_LEADER, NT_CM_APP_CM_LEADER);
} }
//貌似还有这么用的TEAM(2, "cm_leader"),
/** /**
* 安心筑App-工人 * 安心筑App-工人
@ -157,6 +195,16 @@ public class TerminalInfo {
aliasMap.put(STR_TERMINAL_PLAT, NT_OMS_WEB); aliasMap.put(STR_TERMINAL_PLAT, NT_OMS_WEB);
} }
/**
* Screen数据大屏
*/
public static final String NT_SM = "NT_SM";
static {
aliasMap.put(NT_SM, NT_SM);
aliasMap.put(STR_TERMINAL_SM, NT_SM);
aliasMap.put(STR_TERMINAL_SMP, NT_SM);
}
/** /**
* Screen数据大屏 * Screen数据大屏
*/ */
@ -166,6 +214,18 @@ public class TerminalInfo {
aliasMap.put(STR_TERMINAL_SCREEN, NT_SCREEN); aliasMap.put(STR_TERMINAL_SCREEN, NT_SCREEN);
} }
static {
for(Entry<String, String> entry : aliasMap.entrySet()) {
String nt = entry.getValue();
List<String> list = ntLegacyMap.get(nt);
if(list == null) {
list = new ArrayList<String>();
ntLegacyMap.put(nt, list);
}
list.add(entry.getKey());
}
}
private String rawTerminalString; private String rawTerminalString;
private String newTerminalString; private String newTerminalString;
@ -173,9 +233,9 @@ public class TerminalInfo {
public TerminalInfo(String rawTerminalString) { public TerminalInfo(String rawTerminalString) {
this.rawTerminalString = rawTerminalString; this.rawTerminalString = rawTerminalString;
this.newTerminalString = aliasMap.get(rawTerminalString); this.newTerminalString = aliasMap.get(rawTerminalString);
//TODO: 为了调试方便先注释掉这两句@gaowei // TODO: 为了调试方便先注释掉这两句@gaowei
//if (this.newTerminalString == null) // if (this.newTerminalString == null)
// throw new IllegalArgumentException("无效的Terminal" + rawTerminalString); // throw new IllegalArgumentException("无效的Terminal" + rawTerminalString);
} }
public TerminalInfo(String rawTerminalString, String newTerminalString) { public TerminalInfo(String rawTerminalString, String newTerminalString) {
@ -219,7 +279,7 @@ public class TerminalInfo {
public boolean isCMP_APP_ENT_ZB() { public boolean isCMP_APP_ENT_ZB() {
return NT_CMP_APP_ENT_ZB.equals(newTerminalString); return NT_CMP_APP_ENT_ZB.equals(newTerminalString);
} }
public boolean isCMP_APP_PROJ() { public boolean isCMP_APP_PROJ() {
return NT_CMP_APP_PROJ.equals(newTerminalString); return NT_CMP_APP_PROJ.equals(newTerminalString);
} }
@ -232,5 +292,63 @@ public class TerminalInfo {
return NT_CM_APP_CM_WORKER.equals(newTerminalString); return NT_CM_APP_CM_WORKER.equals(newTerminalString);
} }
/**
* 新代码逻辑不要用这个
* @param legacyTerminalString
* @return
*/
@Deprecated
public boolean isLegacy(String legacyTerminalString) {
if (legacyTerminalString == null)
return false;
if (this.rawTerminalString.equals(legacyTerminalString))
return true;
TerminalInfo legacyTM = new TerminalInfo(legacyTerminalString);
if (this.NT().equals(legacyTM.NT())) {
return true;
}
return false;
}
@Override
public String toString() {
return this.newTerminalString;
}
/**
* 新代码逻辑不要用这个
* @return
*/
@Deprecated
public List<String> allNames() {
List<String> list = ntLegacyMap.get(this.newTerminalString);
if(list == null)
return Collections.emptyList();
return list;
}
/**
*
* @param terminal
* @param enums 各种历史的字符串
* @return parse成功就返回enums里的值否则返回原terminal string
*/
public static String parseLegacyTerminal(String terminal, String ... enums) {
TerminalInfo tm = new TerminalInfo(terminal);
for(String e : enums) {
if(tm.isLegacy(e))
return e;
}
return terminal;
}
public static boolean legacyEquals(String t1, String t2) {
TerminalInfo tm1 = new TerminalInfo(t1);
return tm1.isLegacy(t2);
}
public static List<String> allNamesOf(String terminal) {
TerminalInfo tm = new TerminalInfo(terminal);
return tm.allNames();
}
} }

View File

@ -34,7 +34,18 @@ public class UserInfo {
private String realName; private String realName;
private String username; private String username;
/**
* 实名认证的头像历史代码里的faceUrl也是它
*/
private String idFaceUrl;
/**
* 这个是新东西用户自定义的头像630以前没有过
* 估计是平台业务会用到
*/
private String avatarUrl;
/** /**
* 手机号 * 手机号
*/ */

View File

@ -28,11 +28,12 @@ import cn.axzo.framework.auth.domain.UserInfo;
import cn.axzo.framework.auth.domain.UserInfoMap; import cn.axzo.framework.auth.domain.UserInfoMap;
import cn.axzo.framework.auth.enums.EnvEnum; import cn.axzo.framework.auth.enums.EnvEnum;
import cn.azxo.framework.common.logger.logback.PodNamespacePropertyDefiner; import cn.azxo.framework.common.logger.logback.PodNamespacePropertyDefiner;
import cn.azxo.framework.common.model.CommonResponse;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.codec.Base64; import cn.hutool.core.codec.Base64;
import cn.hutool.core.lang.TypeReference; import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.text.CharSequenceUtil; import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpException; import cn.hutool.http.HttpException;
import cn.hutool.http.HttpRequest; import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
@ -67,22 +68,33 @@ public class ContextInfoBuilderAspect {
} }
AuthException.error(Objects.nonNull(httpRequest), "httpRequest cant be null, this is error"); AuthException.error(Objects.nonNull(httpRequest), "httpRequest cant be null, this is error");
Object[] args = parseContextInfoAndReturnArgs(httpRequest, pjp); ContextInfo contextInfo = null;
try { try {
contextInfo = fillContextInfoByRequest(httpRequest);
} catch (Exception e) {
//一般情况是AuthException
return CommonResponse.error(e.getMessage());
}
try {
// 把ContextInfo放到ThreadLocal中
ContextInfoHolder.set(contextInfo);
Object[] args = parseContextInfoAndReturnArgs(httpRequest, pjp, contextInfo);
return pjp.proceed(args); return pjp.proceed(args);
} catch (Exception e) {
return CommonResponse.error(e.getMessage());
} finally { } finally {
ContextInfoHolder.clear(); ContextInfoHolder.clear();
} }
} }
public Object[] parseContextInfoAndReturnArgs(HttpServletRequest request, ProceedingJoinPoint pjp) { public Object[] parseContextInfoAndReturnArgs(HttpServletRequest request, ProceedingJoinPoint pjp, ContextInfo contextInfo) {
// 把ContextInfo注入到函数的入参中 // 把ContextInfo注入到函数的入参中
MethodSignature methodSignature = (MethodSignature) pjp.getSignature(); MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
Method method = methodSignature.getMethod(); Method method = methodSignature.getMethod();
Class<?>[] parameterTypes = method.getParameterTypes(); Class<?>[] parameterTypes = method.getParameterTypes();
Object[] pjpArgs = pjp.getArgs(); Object[] pjpArgs = pjp.getArgs();
ContextInfo contextInfo = fillContextInfoByRequest(request);
if (contextInfo == null) if (contextInfo == null)
return pjpArgs; return pjpArgs;
@ -128,9 +140,6 @@ public class ContextInfoBuilderAspect {
// 定制一些信息的处理 // 定制一些信息的处理
contextInfo.buildCustomInfoByRequest(request); contextInfo.buildCustomInfoByRequest(request);
// 把ContextInfo放到ThreadLocal中
ContextInfoHolder.set(contextInfo);
return contextInfo; return contextInfo;
} }
@ -157,11 +166,26 @@ public class ContextInfoBuilderAspect {
// 有的URI缺少部分header是正常的我就没必要guess有的有必要 // 有的URI缺少部分header是正常的我就没必要guess有的有必要
String response = request.execute().body(); String response = request.execute().body();
// 使用token获取用户信息
AuthException.error(CharSequenceUtil.isNotEmpty(response), "not find user by token from pudge"); try {
return response; TypeReference<Map<String, Object>> mapTypeReference = new TypeReference<Map<String, Object>>() {};
Map<String, Object> map = JSONUtil.toBean(response, mapTypeReference, false);
if(map.containsKey(AuthConstants.USER_INFO)) {
response = String.valueOf(map.get(AuthConstants.USER_INFO));
// 使用token获取用户信息
AuthException.error(CharSequenceUtil.isNotEmpty(response), "not find user by token from pudge");
return response;
} else if(map.containsKey("error")){
throw new AuthException(map.get("error").toString());
} else {
throw new AuthException("无法解析鉴权认证请求的返回值token=" + contextInfo.getToken());
}
} catch (Exception e) {
throw new AuthException("解析鉴权认证请求出错, token="+contextInfo.getToken(), e);
}
} catch (HttpException e) { } catch (HttpException e) {
throw new AuthException("call pudge get/user error."); throw new AuthException("call pudge get/user error. token=" + contextInfo.getToken());
} }
} }
@ -214,22 +238,35 @@ public class ContextInfoBuilderAspect {
contextInfo.setSystemAndDeviceInfo(sdInfo); contextInfo.setSystemAndDeviceInfo(sdInfo);
contextInfo.setToken(request.getHeader(AuthConstants.HEADER_TOKEN)); contextInfo.setToken(request.getHeader(AuthConstants.HEADER_TOKEN));
contextInfo.setTerminalInfo(new TerminalInfo(request.getHeader(AuthConstants.HEADER_TERMINAL)));
contextInfo.setTenantId(nullSafeParseLong(request.getHeader(AuthConstants.HEADER_TENANT_ID))); contextInfo.setTenantId(nullSafeParseLong(request.getHeader(AuthConstants.HEADER_TENANT_ID)));
contextInfo.setSaasTenantId(nullSafeParseLong(request.getHeader(AuthConstants.HEADER_SAAS_TENANT_ID))); contextInfo.setSaasTenantId(nullSafeParseLong(request.getHeader(AuthConstants.HEADER_SAAS_TENANT_ID)));
contextInfo.setOuId(nullSafeParseLong(request.getHeader(AuthConstants.HEADER_OU_ID))); contextInfo.setOuId(nullSafeParseLong(request.getHeader(AuthConstants.HEADER_OU_ID)));
contextInfo.setWorkspaceId(nullSafeParseLong(request.getHeader(AuthConstants.HEADER_WORKSPACE_ID))); contextInfo.setWorkspaceId(nullSafeParseLong(request.getHeader(AuthConstants.HEADER_WORKSPACE_ID)));
String terminalHeader = request.getHeader(AuthConstants.HEADER_TERMINAL);
String terminalSession = StpUtil.getLoginDevice();
String terminal = terminalHeader;
if (null == terminalHeader || "".equals(terminalHeader)) {
log.warn("请求缺少terminal headertoken={}。暂时使用session中的补齐terminal={}。", contextInfo.getToken(),
terminalSession);
terminal = terminalSession;
} else if (TerminalInfo.legacyEquals(terminalHeader, terminalSession)) {
log.warn("请求缺少terminal header与session中不一致token={}。暂时使用request中的terminal={}session terminal={}",
contextInfo.getToken(), terminalHeader, terminalSession);
terminal = terminalSession;
}
contextInfo.setTerminalInfo(new TerminalInfo(terminal));
contextInfo.setVisitTo(request.getHeader(AuthConstants.VISIT_TO)); contextInfo.setVisitTo(request.getHeader(AuthConstants.VISIT_TO));
} }
public void buildUserInfo(ContextInfo contextInfo, String authResultJson) { public void buildUserInfo(ContextInfo contextInfo, String authResultJson) {
log.info("buildUserInfo-->authResultJson:{},contextInfo:{}",authResultJson,JSONUtil.toJsonStr(contextInfo)); log.info("buildUserInfo-->authResultJson:{},contextInfo:{}", authResultJson, JSONUtil.toJsonStr(contextInfo));
UserInfo userInfo = new UserInfo(); UserInfo userInfo = new UserInfo();
TypeReference<Map<String, Object>> mapTypeReference = new TypeReference<Map<String, Object>>() { TypeReference<Map<String, Object>> mapTypeReference = new TypeReference<Map<String, Object>>() {
}; };
Map<String, Object> map = JSONUtil.toBean(authResultJson, mapTypeReference, false); Map<String, Object> userinfoMap = JSONUtil.toBean(authResultJson, mapTypeReference, false);
Map<String, Object> userinfoMap = JSONUtil.toBean((String) map.get("userinfo"), mapTypeReference, false);
// 对bean进行封装属性 // 对bean进行封装属性
BeanUtil.fillBeanWithMap(userinfoMap, userInfo, false); BeanUtil.fillBeanWithMap(userinfoMap, userInfo, false);