修改经办段统一门户登录

This commit is contained in:
sh
2025-11-16 11:19:37 +08:00
parent 4716127fc2
commit 31662c3a11
5 changed files with 230 additions and 111 deletions

View File

@@ -1,7 +1,10 @@
package com.ruoyi.cms.util.oauth;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.TypeReference;
import com.ruoyi.common.core.domain.entity.tymh.authority.QxUserRole;
import com.ruoyi.common.core.domain.entity.tymh.nwToken.NwTokenResult;
import com.ruoyi.common.core.domain.entity.tymh.nwToken.NwUserInfoResult;
import com.ruoyi.common.utils.StringUtils;
@@ -11,6 +14,7 @@ import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeoutException;
import org.slf4j.Logger;
@@ -24,53 +28,38 @@ public class OauthClient {
private static final Logger log = LoggerFactory.getLogger(OauthClient.class);
/*====================== 内网 ======================*/
// 网关请求-内网获取token
@Value("${oauth.usptnw.nwGatewayGetTokenUrl}")
private String nwGatewayGetTokenUrl;
// 网关请求-内网获取用户信息
@Value("${oauth.usptnw.nwGatewayGetUserInfoUrl}")
private String nwGatewayGetUserInfoUrl;
/*====================== 外网 ======================*/
//post-外网注册地址
@Value("${oauth.usptww.wwRegisterPostUrl}")
private String wwRegisterPostUrl;
// post-外网获取token
@Value("${oauth.usptww.wwTokenPostUrl}")
private String wwTokenPostUrl;
//post-外网获取用户信息
@Value("${oauth.usptww.wwQueryWebPersonalInfoPostUrl}")
private String wwQueryWebPersonalInfoPostUrl;
//post-外网获取单位信息
@Value("${oauth.usptww.wwQueryWebEnterpriseInfoPostUrl}")
private String wwQueryWebEnterpriseInfoPostUrl;
/*====================== 统一门户 ======================*/
//用户新增接口
@Value("${oauth.tyAddUserUrl}")
private String tyAddUserUrl;
//获取当前用户有权系统列表
@Value("${oauth.tyQueryUserSysListUrl}")
private String tyQueryUserSysListUrl;
//获取当前用户有权角色列表
@Value("${oauth.tyQueryUserRoleListUrl}")
private String tyQueryUserRoleListUrl;
//获取角色功能权限信息
@Value("${oauth.tyQueryRoleInfoUrl}")
private String tyQueryRoleInfoUrl;
//获取用户详细信息
@Value("${oauth.tyQueryUserInfo}")
private String tyQueryUserInfo;
//获取机构详细信息
@Value("${oauth.tyQueryUnitInfo}")
private String tyQueryUnitInfo;
//客户端id
@Value("${oauth.appid}")
private String appid;
//授权码
@Value("${oauth.clientsecretkey}")
private String clientsecretkey;
// 超时配置
@Value("${oauth.connect-timeout:10}")
private int connectTimeout;
@Value("${oauth.read-timeout:30}")
@@ -80,7 +69,6 @@ public class OauthClient {
/**
* 获取经办段token
* @return
*/
public NwTokenResult nwGetToken(String code) throws IOException, TimeoutException {
if (StringUtils.isEmpty(code)) {
@@ -119,7 +107,6 @@ public class OauthClient {
/**
* 获取经办段用户id
* @return
*/
public NwUserInfoResult nwGetUserInfo(String accessToken) throws IOException, TimeoutException {
Map<String, Object> params = new HashMap<>(2);
@@ -134,120 +121,177 @@ public class OauthClient {
);
}
/**
* 根据用户id查询用户角色列表
* @param userid
* @return
* @throws IOException
* @throws TimeoutException
*/
public List<QxUserRole> getUserRoleList(Long userid) throws IOException, TimeoutException {
Map<String, Object> params = new HashMap<>(2);
params.put("appid", appid);
params.put("userid", String.valueOf(userid));
return executePostRequestResultList(
tyQueryUserRoleListUrl,
params,
QxUserRole.class,
"根据用户id获取用户角色列表"
);
}
/**
* 公共POST请求执行方法
* @param url 请求URL
* @param params 请求参数
* @param typeReference 响应类型引用
* @param operationName 操作名称(用于日志和异常信息)
* @return 响应数据对象
*/
private <T> T executePostRequest(String url, Map<String, Object> params,
TypeReference<Response<T>> typeReference, String operationName)
throws IOException, TimeoutException {
String responseJson = null;
try {
responseJson = HttpUtils.doPostJson(
url,
params,
connectTimeout,
readTimeout,
writeTimeout
);
}catch (Exception e){
e.printStackTrace();
}
String responseJson = HttpUtils.doPostJson(
url,
params,
connectTimeout,
readTimeout,
writeTimeout
);
return validateResponse(responseJson, operationName, typeReference);
}
/**
* 公共响应校验工具方法(网关响应 + 业务 errflag 校验)
* 公共POST请求执行方法处理List
*/
private <T> List<T> executePostRequestResultList(String url, Map<String, Object> params,
Class<T> clazz, String operationName)
throws IOException, TimeoutException {
String responseJson = HttpUtils.doPostJson(
url,
params,
connectTimeout,
readTimeout,
writeTimeout
);
return parseMapOrDataArray(responseJson, operationName, clazz);
}
/**
* 简化后的响应校验方法(已移除网关返回码判断)
*/
private <T> T validateResponse(String responseJson, String operationName, TypeReference<Response<T>> typeReference) {
// 1. 校验响应是否为
// 1. 校验响应空
if (StringUtils.isEmpty(responseJson)) {
String errorMsg = operationName + "失败:接口返回空响应";
String errorMsg = operationName + "失败:接口返回空";
log.error(errorMsg);
throw new BusinessException("EMPTY_RESPONSE", errorMsg);
throw new RuntimeException(errorMsg);
}
log.debug("{}接口返回原始数据: {}", operationName, responseJson);
log.debug("{}返回数据: {}", operationName, responseJson);
// 2. 解析网关响应(外层 appcode 校验)
// 2. 解析响应并校验基础格式
Response<T> gatewayResponse = JSON.parseObject(responseJson, typeReference);
if (gatewayResponse == null) {
String errorMsg = operationName + "失败:网关响应格式异常(无法解析)";
String errorMsg = operationName + "失败:响应格式错误";
log.error("{} | 原始响应: {}", errorMsg, responseJson);
throw new BusinessException("GATEWAY_PARSE_ERROR", errorMsg);
}
if (!"0".equals(gatewayResponse.getAppcode())) {
String errorMsg = String.format("%s失败网关响应失败 | appcode: %s, msg: %s",
operationName, gatewayResponse.getAppcode(), gatewayResponse.getMsg());
log.error("{} | 原始响应: {}", errorMsg, responseJson);
throw new BusinessException(gatewayResponse.getAppcode(), errorMsg);
throw new RuntimeException(errorMsg);
}
// 3. 校验业务数据移除了网关appcode的判断逻辑
T data = gatewayResponse.getData();
if (data == null) {
String errorMsg = operationName + "失败:响应data字段为空";
String errorMsg = operationName + "失败:业务数据为空";
log.error("{} | 原始响应: {}", errorMsg, responseJson);
throw new BusinessException("DATA_EMPTY", errorMsg);
throw new RuntimeException(errorMsg);
}
if (data instanceof ErrFlagResponse) {
ErrFlagResponse errFlagResponse = (ErrFlagResponse) data;
if (!errFlagResponse.isSuccess()) {
String errorMsg = String.format("%s失败%s错误标识%s",
operationName, errFlagResponse.getErrtext(), errFlagResponse.getErrflag());
log.error("{} | 原始响应: {}", errorMsg, responseJson);
throw new BusinessException(errFlagResponse.getErrflag(), errorMsg);
}
}
// 6. 所有校验通过,返回业务数据
return data;
}
/**
* 解析List
* @param jsonStr
* @param clazz
* @return
*/
public static <T> List<T> parseMapOrDataArray(String jsonStr, String operationName, Class<T> clazz) {
if (StringUtils.isEmpty(jsonStr)) {
String errorMsg = operationName + "失败:接口返回空";
log.error(errorMsg);
throw new RuntimeException(errorMsg);
}
JSONObject jsonObject;
try {
jsonObject = JSON.parseObject(jsonStr);
} catch (Exception e) {
String errorMsg = operationName + "失败:响应格式错误(非合法 JSON";
log.error("{} | 原始响应: {}", errorMsg, jsonStr, e);
throw new RuntimeException(errorMsg, e);
}
if (jsonObject == null) {
String errorMsg = operationName + "失败:响应格式错误(解析后为 null";
log.error("{} | 原始响应: {}", errorMsg, jsonStr);
throw new RuntimeException(errorMsg);
}
JSONArray targetArray = getJSONArraySafe(jsonObject, "map");
if (targetArray == null || targetArray.isEmpty()) {
targetArray = getJSONArraySafe(jsonObject, "data");
}
if (targetArray == null || targetArray.isEmpty()) {
String errorMsg = operationName + "失败业务数据为空map/data 字段无有效数组)";
log.error("{} | 原始响应: {}", errorMsg, jsonStr);
throw new RuntimeException(errorMsg);
}
List<T> dataList;
try {
dataList = JSON.parseArray(targetArray.toJSONString(), clazz);
} catch (Exception e) {
String errorMsg = operationName + "失败:数据解析失败(数组元素与目标类不匹配)";
log.error("{} | 原始响应: {} | 目标类: {}", errorMsg, jsonStr, clazz.getName(), e);
throw new RuntimeException(errorMsg, e);
}
if (dataList == null || dataList.isEmpty()) {
String errorMsg = operationName + "失败:解析后业务数据为空";
log.error("{} | 原始响应: {}", errorMsg, jsonStr);
throw new RuntimeException(errorMsg);
}
return dataList;
}
/**
* 避免空值和类型转换异常
* @param jsonObject
* @param key
* @return
*/
private static JSONArray getJSONArraySafe(JSONObject jsonObject, String key) {
if (jsonObject == null || StringUtils.isEmpty(key)) {
return null;
}
if (!jsonObject.containsKey(key)) {
return null;
}
Object value = jsonObject.get(key);
return (value instanceof JSONArray) ? (JSONArray) value : null;
}
/**
* 静态返回解析
* @param <T>
*/
public static class Response<T> {
private String appcode;
private String code;
private String msg;
private T data;
private Object map;
// Getter仅保留需要的字段setter可选
public String getAppcode() { return appcode; }
public String getMsg() { return msg; }
public T getData() { return data; }
public void setAppcode(String appcode) { this.appcode = appcode; }
public void setMsg(String msg) { this.msg = msg; }
public void setData(T data) { this.data = data; }
}
public class BusinessException extends RuntimeException {
private String code; // 错误码(可关联门户错误码)
public BusinessException(String message) {
super(message);
this.code = "BUSINESS_ERROR";
}
public BusinessException(String code, String message) {
super(message);
this.code = code;
}
// Getter
public String getCode() {
return code;
}
}
public interface ErrFlagResponse {
String getErrflag();
String getErrtext();
// 默认方法判断是否成功0=成功1=失败)
default boolean isSuccess() {
return "0".equals(getErrflag());
}
}
}