feat: 增加登陆相关信息
This commit is contained in:
parent
a95e2cc449
commit
37b646f708
@ -36,6 +36,11 @@
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>transmittable-thread-local</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@ -2,6 +2,7 @@ package cn.axzo.foundation.web.support.config;
|
||||
|
||||
import cn.axzo.foundation.util.FastjsonUtils;
|
||||
import cn.axzo.foundation.web.support.AppRuntime;
|
||||
import cn.axzo.foundation.web.support.context.AxContextInterceptor;
|
||||
import cn.axzo.foundation.web.support.exception.AbstractExceptionHandler;
|
||||
import cn.axzo.foundation.web.support.interceptors.PrettyPrintInterceptor;
|
||||
import cn.axzo.foundation.web.support.interceptors.PrintVerboseInterceptor;
|
||||
@ -187,6 +188,7 @@ public class DefaultWebMvcConfig extends DelegatingWebMvcConfiguration implement
|
||||
registry.addInterceptor(e);
|
||||
});
|
||||
}
|
||||
registry.addInterceptor(new AxContextInterceptor(appRuntime));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -0,0 +1,89 @@
|
||||
package cn.axzo.foundation.web.support.context;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.ttl.TransmittableThreadLocal;
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.io.BaseEncoding;
|
||||
import lombok.*;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class AxContext {
|
||||
private static final TransmittableThreadLocal<AxContext> CONTEXT = new TransmittableThreadLocal();
|
||||
private static final TransmittableThreadLocal<HttpServletRequest> REQUEST = new TransmittableThreadLocal();
|
||||
|
||||
private AxUser axUser;
|
||||
private Long ouId;
|
||||
|
||||
public static void set(AxContext contextInfo) {
|
||||
CONTEXT.set(contextInfo);
|
||||
}
|
||||
|
||||
public static Optional<AxContext> get() {
|
||||
return Optional.ofNullable(CONTEXT.get());
|
||||
}
|
||||
|
||||
public static void clear() {
|
||||
CONTEXT.remove();
|
||||
}
|
||||
|
||||
public static void setRequest(HttpServletRequest request) {
|
||||
REQUEST.set(request);
|
||||
}
|
||||
|
||||
public static Optional<HttpServletRequest> getRequest() {
|
||||
return Optional.ofNullable(REQUEST.get());
|
||||
}
|
||||
|
||||
|
||||
public static boolean init() {
|
||||
if (!getRequest().isPresent()) {
|
||||
return false;
|
||||
}
|
||||
HttpServletRequest request = getRequest().get();
|
||||
AxContext context = AxContext.builder().build();
|
||||
Boolean[] initialled = Arrays.stream(HeaderEnum.values())
|
||||
.map(e -> e.getFiller().apply(request, context))
|
||||
.toArray(Boolean[]::new);
|
||||
//所有的header设置成功才算成功
|
||||
if (BooleanUtils.and(initialled)) {
|
||||
set(context);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum HeaderEnum {
|
||||
USER("用户信息", (request, context) -> {
|
||||
String userHeader = request.getHeader("userinfo");
|
||||
if (Strings.isNullOrEmpty(userHeader)) {
|
||||
return false;
|
||||
}
|
||||
String userStr = new String(BaseEncoding.base64().decode(userHeader), Charsets.UTF_8);
|
||||
context.setAxUser(JSONObject.parseObject(userStr, AxUser.class));
|
||||
return true;
|
||||
}),
|
||||
OU_ID("部门ID", (request, context) -> {
|
||||
String ouIdHeader = request.getHeader("ouId");
|
||||
if (Strings.isNullOrEmpty(ouIdHeader)) {
|
||||
return false;
|
||||
}
|
||||
context.setOuId(Long.parseLong(ouIdHeader));
|
||||
return true;
|
||||
});
|
||||
|
||||
private final String desc;
|
||||
private final BiFunction<HttpServletRequest, AxContext, Boolean> filler;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,86 @@
|
||||
package cn.axzo.foundation.web.support.context;
|
||||
|
||||
import cn.axzo.foundation.enums.AppEnvEnum;
|
||||
import cn.axzo.foundation.web.support.AppRuntime;
|
||||
import cn.axzo.foundation.web.support.rpc.HttpClient;
|
||||
import cn.axzo.foundation.web.support.rpc.OkHttpClientImpl;
|
||||
import cn.axzo.foundation.web.support.rpc.RequestParams;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 1. 从容器内调用, 端->apisix->this server可以从header中直接获取
|
||||
* 2. 非prd环境支持Authorization: Raw {personId:xxx}
|
||||
* 3. 非prd环境支持通过token到puge换
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class AxContextInterceptor implements HandlerInterceptor {
|
||||
private final AppRuntime appRuntime;
|
||||
|
||||
private final static HttpClient HTTP_CLIENT = OkHttpClientImpl.builder().build();
|
||||
private final static Map<AppEnvEnum, String> ENV_HOSTS = ImmutableMap.of(
|
||||
AppEnvEnum.local, "http://test-api.axzo.cn/pudge/webApi/oauth/apisix/authentication",
|
||||
AppEnvEnum.dev, "http://dev-app.axzo.cn/pudge/webApi/oauth/apisix/authentication",
|
||||
AppEnvEnum.test, "http://test-api.axzo.cn/pudge/webApi/oauth/apisix/authentication",
|
||||
AppEnvEnum.pre, "http://pre-api.axzo.cn/pudge/webApi/oauth/apisix/authentication"
|
||||
);
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
|
||||
AxContext.clear();
|
||||
AxContext.setRequest(request);
|
||||
boolean initialled = AxContext.init();
|
||||
if (initialled) {
|
||||
return true;
|
||||
}
|
||||
String authorization = request.getHeader("Authorization");
|
||||
if (!Strings.isNullOrEmpty(authorization) && appRuntime.getEnv() != AppEnvEnum.prd) {
|
||||
return initByAuthorization(authorization);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
|
||||
Exception ex) {
|
||||
AxContext.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* 支持传入明文的authentication 或者通过puge接口支持
|
||||
* 明文格式: authentication: Raw {ouid:xxx, axUser:{personId:xxx}}
|
||||
* puge接口返回结果参考 test.resources.authentication.json
|
||||
*/
|
||||
private boolean initByAuthorization(String authorization) {
|
||||
AxContext context = null;
|
||||
if (authorization.startsWith("Raw")) {
|
||||
context = JSONObject.parseObject(StringUtils.removeStart(authorization, "Raw "), AxContext.class);
|
||||
}
|
||||
if (authorization.startsWith("Bearer")) {
|
||||
String result = HTTP_CLIENT.get(ENV_HOSTS.get(appRuntime.getEnv()), RequestParams.FormParams.builder()
|
||||
.headers(ImmutableMap.of("Authorization", authorization))
|
||||
.build());
|
||||
JSONObject userinfo = JSONObject.parseObject(result).getJSONObject("userinfo");
|
||||
context = AxContext.builder()
|
||||
.ouId(userinfo.getLong("ouId"))
|
||||
.axUser(userinfo.toJavaObject(AxUser.class))
|
||||
.build();
|
||||
}
|
||||
if (context != null) {
|
||||
AxContext.set(context);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
package cn.axzo.foundation.web.support.context;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class AxUser {
|
||||
|
||||
private Long personId;
|
||||
|
||||
private VerifyStatusEnum verifyStatus;
|
||||
|
||||
private String realName;
|
||||
|
||||
private transient String phoneNumber;
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum VerifyStatusEnum {
|
||||
//状态 0 - 未激活, 1 - 已激活,2 - 禁用,3- 认证失败
|
||||
NOT_VERIFIED(0, "未认证"),
|
||||
VERIFYING(1, "认证中"),
|
||||
VERIFY_SUCCESS(2, "认证成功"),
|
||||
VERIFY_FAILED(3, "认证失败"),
|
||||
;
|
||||
private final Integer code;
|
||||
private final String message;
|
||||
}
|
||||
}
|
||||
41
web-support-lib/src/test/resources/authentication.json
Normal file
41
web-support-lib/src/test/resources/authentication.json
Normal file
@ -0,0 +1,41 @@
|
||||
|
||||
{
|
||||
"appVersion": "0",
|
||||
"ouType": 6,
|
||||
"enabled": true,
|
||||
"acntId": 9000456,
|
||||
"idFaceUrl": "https://axzo-test.oss-cn-chengdu.aliyuncs.com/idcard/idfaceurl/21664884838922395543357.jpg",
|
||||
"verifyStatus": "VERIFY_SUCCESS",
|
||||
"identityType": 5,
|
||||
"ouId": 5144,
|
||||
"id": 9000456,
|
||||
"workspaceId": 335,
|
||||
"avatarUrl": "https://industrial-public.oss-cn-shanghai.aliyuncs.com/avator/default_avator.png",
|
||||
"sex": "2",
|
||||
"ipAddress": "10.0.3.225",
|
||||
"acctId": 9000456,
|
||||
"loginDevice": "NT_OMS_WEB",
|
||||
"terminal": "NT_OMS_WEB",
|
||||
"userId": 2003154,
|
||||
"realName": "金海洋",
|
||||
"faceUrl": "https://axzo-test.oss-cn-chengdu.aliyuncs.com/idcard/idfaceurl/21664884838922395543357.jpg",
|
||||
"workspaceType": 6,
|
||||
"phoneNumber": "18008065266",
|
||||
"identityId": 2003154,
|
||||
"verifiedStatus": 2,
|
||||
"personId": 9000456,
|
||||
"legacyGuess": {
|
||||
"ouType": 6,
|
||||
"workspaceType": 6,
|
||||
"guessTerminal": "__GUESS_OK__",
|
||||
"guessOU": "__GUESS_OK__",
|
||||
"ouId": 5144,
|
||||
"guessWorkspace": "__GUESS_OK__",
|
||||
"guessSaasTenant": "__NO_NEED__",
|
||||
"workspaceJoinType": 0,
|
||||
"saasTenantId": 0,
|
||||
"newTerminal": "NT_OMS_WEB",
|
||||
"workspaceId": 335
|
||||
},
|
||||
"axzoId": 9000456
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user