1.修改1101(求职者)、1102(招聘者)、1103(网格员)、1104(内部工作者)

2.添加门户认证的类
This commit is contained in:
sh
2025-11-15 14:04:05 +08:00
parent 6b376ad8e1
commit 4716127fc2
9 changed files with 680 additions and 11 deletions

View File

@@ -1,7 +1,5 @@
package com.ruoyi.cms.util;
import com.ruoyi.cms.domain.query.ESJobSearch;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -10,7 +8,8 @@ import java.util.stream.Collectors;
public class StringUtil {
public static final Long COMPANY_ADMIN_ROLE_KEY = 100L;
/*1101(求职者)、1102(招聘者)、1103(网格员)、1104(内部工作者)*/
public static final Long COMPANY_ADMIN_ROLE_KEY = 1002L;
/**
* 企业用户
@@ -20,11 +19,11 @@ public class StringUtil {
/**
* pc端-求职者
*/
public static final String SYS_QZZ = "2";
public static final String SYS_QZZ = "1101";
/**
* pc端-企业
*/
public static final String SYS_QY = "100";
public static final String SYS_QY = "1102";
public static Boolean isEmptyOrNull(String s){
if(Objects.isNull(s)){return true;}

View File

@@ -0,0 +1,151 @@
package com.ruoyi.cms.util.oauth;
import com.alibaba.fastjson2.JSON;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
import java.io.IOException;
import java.net.SocketTimeoutException;
import java.net.URLEncoder;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* 简化版 HTTP 客户端工具类仅保留核心POST功能保留超时配置
*/
public class HttpUtils {
private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);
// 保留默认超时配置
private static final int DEFAULT_CONNECT_TIMEOUT = 10;
private static final int DEFAULT_READ_TIMEOUT = 30;
private static final int DEFAULT_WRITE_TIMEOUT = 30;
// 媒体类型常量
public static final MediaType JSON_MEDIA_TYPE = MediaType.parse("application/json; charset=utf-8");
public static final MediaType FORM_MEDIA_TYPE = MediaType.parse("application/x-www-form-urlencoded; charset=utf-8");
// OkHttp 客户端(单例)
private static final OkHttpClient OK_HTTP_CLIENT;
static {
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.connectTimeout(DEFAULT_CONNECT_TIMEOUT, TimeUnit.SECONDS)
.readTimeout(DEFAULT_READ_TIMEOUT, TimeUnit.SECONDS)
.writeTimeout(DEFAULT_WRITE_TIMEOUT, TimeUnit.SECONDS);
OK_HTTP_CLIENT = builder.build();
}
/**
* POST JSON请求默认超时
*/
public static String doPostJson(String url, Map<String, Object> params) throws TimeoutException, IOException {
return doPostJson(url, params, DEFAULT_CONNECT_TIMEOUT, DEFAULT_READ_TIMEOUT, DEFAULT_WRITE_TIMEOUT);
}
/**
* POST JSON请求自定义超时
*/
public static String doPostJson(String url, Map<String, Object> params, int connectTimeout, int readTimeout, int writeTimeout)
throws TimeoutException, IOException {
String jsonParams = CollectionUtils.isEmpty(params) ? "{}" : JSON.toJSONString(params);
return doPost(url, jsonParams, JSON_MEDIA_TYPE, null, connectTimeout, readTimeout, writeTimeout);
}
/**
* POST 表单请求(默认超时)
*/
public static String doPostForm(String url, Map<String, Object> params) throws TimeoutException, IOException {
return doPostForm(url, params, null, DEFAULT_CONNECT_TIMEOUT, DEFAULT_READ_TIMEOUT, DEFAULT_WRITE_TIMEOUT);
}
/**
* POST 表单请求(自定义超时)
*/
public static String doPostForm(String url, Map<String, Object> params, Map<String, String> headers,
int connectTimeout, int readTimeout, int writeTimeout)
throws TimeoutException, IOException {
FormBody.Builder formBuilder = new FormBody.Builder();
if (!CollectionUtils.isEmpty(params)) {
params.forEach((key, value) -> {
if (value != null) {
formBuilder.add(encodeParam(key), value.toString());
}
});
}
RequestBody requestBody = formBuilder.build();
Request.Builder requestBuilder = new Request.Builder()
.url(url)
.post(requestBody)
.header("Content-Type", FORM_MEDIA_TYPE.toString());
addHeaders(requestBuilder, headers);
return executeRequest(requestBuilder.build(), connectTimeout, readTimeout, writeTimeout);
}
/**
* 通用POST方法
*/
private static String doPost(String url, String content, MediaType mediaType, Map<String, String> headers,
int connectTimeout, int readTimeout, int writeTimeout)
throws TimeoutException, IOException {
if (mediaType == null) {
mediaType = JSON_MEDIA_TYPE;
}
RequestBody requestBody = RequestBody.create(mediaType,content);
Request.Builder requestBuilder = new Request.Builder()
.url(url)
.post(requestBody)
.header("Content-Type", mediaType.toString());
addHeaders(requestBuilder, headers);
return executeRequest(requestBuilder.build(), connectTimeout, readTimeout, writeTimeout);
}
/**
* 执行请求核心方法
*/
private static String executeRequest(Request request, int connectTimeout, int readTimeout, int writeTimeout)
throws TimeoutException, IOException {
// 保留超时配置覆盖能力
OkHttpClient tempClient = OK_HTTP_CLIENT.newBuilder()
.connectTimeout(connectTimeout, TimeUnit.SECONDS)
.readTimeout(readTimeout, TimeUnit.SECONDS)
.writeTimeout(writeTimeout, TimeUnit.SECONDS)
.build();
try (Response response = tempClient.newCall(request).execute()) {
return response.body() != null ? response.body().string() : "";
} catch (SocketTimeoutException e) {
throw new TimeoutException(String.format("HTTP 请求超时 | URL: %s | 超时配置: 连接%d秒, 读取%d秒, 写入%d秒",
request.url(), connectTimeout, readTimeout, writeTimeout));
}
}
/**
* 参数编码
*/
private static String encodeParam(String param) {
try {
return URLEncoder.encode(param, "UTF-8");
} catch (Exception e) {
log.warn("参数编码失败 | param: {}", param, e);
return param;
}
}
/**
* 添加请求头
*/
private static void addHeaders(Request.Builder requestBuilder, Map<String, String> headers) {
if (!CollectionUtils.isEmpty(headers)) {
headers.forEach(requestBuilder::header);
}
}
}

View File

@@ -0,0 +1,253 @@
package com.ruoyi.cms.util.oauth;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.TypeReference;
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;
import com.ruoyi.common.utils.crypto.CryptoUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeoutException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* OAuth2.0 认证工具类(合并相似方法)
*/
@Component
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}")
private int readTimeout;
@Value("${oauth.write-timeout:30}")
private int writeTimeout;
/**
* 获取经办段token
* @return
*/
public NwTokenResult nwGetToken(String code) throws IOException, TimeoutException {
if (StringUtils.isEmpty(code)) {
log.error("获取Token失败授权码code不能为空");
throw new IllegalArgumentException("授权码code不能为空");
}
String decryptedCode;
try {
decryptedCode = CryptoUtil.sm2Decrypt(clientsecretkey, code);
if (StringUtils.isEmpty(decryptedCode)) {
throw new RuntimeException("授权码解密后为空");
}
} catch (Exception e) {
log.error("授权码解密失败 | 原始code: {}", code, e);
throw new RuntimeException("授权码解密失败:" + e.getMessage(), e);
}
Map<String, Object> params = new HashMap<>(2);
params.put("appid", appid);
params.put("code", decryptedCode);
NwTokenResult result = executePostRequest(
nwGatewayGetTokenUrl,
params,
new TypeReference<Response<NwTokenResult>>() {},
"获取Token"
);
if (StringUtils.isEmpty(result.getAccessToken())) {
throw new RuntimeException("Token获取失败返回的accessToken为空");
}
return result;
}
/**
* 获取经办段用户id
* @return
*/
public NwUserInfoResult nwGetUserInfo(String accessToken) throws IOException, TimeoutException {
Map<String, Object> params = new HashMap<>(2);
params.put("appid", appid);
params.put("access_token", accessToken);
return executePostRequest(
nwGatewayGetUserInfoUrl,
params,
new TypeReference<Response<NwUserInfoResult>>() {},
"获取用户信息"
);
}
/**
* 公共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();
}
return validateResponse(responseJson, operationName, typeReference);
}
/**
* 公共响应校验工具方法(网关响应 + 业务 errflag 校验)
*/
private <T> T validateResponse(String responseJson, String operationName, TypeReference<Response<T>> typeReference) {
// 1. 校验响应是否为空
if (StringUtils.isEmpty(responseJson)) {
String errorMsg = operationName + "失败:接口返回空响应";
log.error(errorMsg);
throw new BusinessException("EMPTY_RESPONSE", errorMsg);
}
log.debug("{}接口返回原始数据: {}", operationName, responseJson);
// 2. 解析网关响应(外层 appcode 校验)
Response<T> gatewayResponse = JSON.parseObject(responseJson, typeReference);
if (gatewayResponse == null) {
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);
}
T data = gatewayResponse.getData();
if (data == null) {
String errorMsg = operationName + "失败响应data字段为空";
log.error("{} | 原始响应: {}", errorMsg, responseJson);
throw new BusinessException("DATA_EMPTY", 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;
}
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 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());
}
}
}