mirror of
https://github.com/PowerJob/PowerJob.git
synced 2025-07-17 00:00:04 +08:00
feat: open-api support auth
This commit is contained in:
parent
c04cb08390
commit
84b90a366c
@ -0,0 +1,63 @@
|
|||||||
|
package tech.powerjob.client;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
import tech.powerjob.client.common.Protocol;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端配置
|
||||||
|
*
|
||||||
|
* @author 程序帕鲁
|
||||||
|
* @since 2024/2/20
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ToString
|
||||||
|
public class ClientConfig implements Serializable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行器 AppName
|
||||||
|
*/
|
||||||
|
private String appName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行器密码
|
||||||
|
*/
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 地址列表,支持格式:
|
||||||
|
* - IP:Port, eg: 192.168.1.1:7700
|
||||||
|
* - 域名, eg: powerjob.apple-inc.com
|
||||||
|
*/
|
||||||
|
private List<String> addressList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端通讯协议
|
||||||
|
*/
|
||||||
|
private Protocol protocol = Protocol.HTTP;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 连接超时时间
|
||||||
|
*/
|
||||||
|
private Integer connectionTimeout;
|
||||||
|
/**
|
||||||
|
* 指定了等待服务器响应数据的最长时间。更具体地说,这是从服务器开始返回响应数据(包括HTTP头和数据)后,客户端读取数据的超时时间
|
||||||
|
*/
|
||||||
|
private Integer readTimeout;
|
||||||
|
/**
|
||||||
|
* 指定了向服务器发送数据的最长时间。这是从客户端开始发送数据(如POST请求的正文)到数据完全发送出去的时间
|
||||||
|
*/
|
||||||
|
private Integer writeTimeout;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认携带的请求头
|
||||||
|
* 用于流量被基础设施识别
|
||||||
|
*/
|
||||||
|
private Map<String, String> defaultHeaders;
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package tech.powerjob.client.common;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Protocol
|
||||||
|
*
|
||||||
|
* @author tjq
|
||||||
|
* @since 2024/2/20
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
public enum Protocol {
|
||||||
|
|
||||||
|
HTTP("http"),
|
||||||
|
|
||||||
|
HTTPS("https");
|
||||||
|
|
||||||
|
private final String protocol;
|
||||||
|
|
||||||
|
Protocol(String protocol) {
|
||||||
|
this.protocol = protocol;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return protocol;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package tech.powerjob.client.module;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* App 鉴权请求
|
||||||
|
*
|
||||||
|
* @author tjq
|
||||||
|
* @since 2024/2/19
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ToString
|
||||||
|
public class AppAuthRequest implements Serializable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用名称
|
||||||
|
*/
|
||||||
|
private String appName;
|
||||||
|
/**
|
||||||
|
* 加密后密码
|
||||||
|
*/
|
||||||
|
private String encryptedPassword;
|
||||||
|
/**
|
||||||
|
* 额外参数,方便开发者传递其他参数
|
||||||
|
*/
|
||||||
|
private Map<String, Object> extra;
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package tech.powerjob.client.module;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* App 鉴权响应
|
||||||
|
*
|
||||||
|
* @author tjq
|
||||||
|
* @since 2024/2/21
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ToString
|
||||||
|
public class AppAuthResult implements Serializable {
|
||||||
|
|
||||||
|
private Long appId;
|
||||||
|
|
||||||
|
private String token;
|
||||||
|
|
||||||
|
private String extra;
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package tech.powerjob.client.service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求服务
|
||||||
|
*
|
||||||
|
* @author tjq
|
||||||
|
* @since 2024/2/20
|
||||||
|
*/
|
||||||
|
public interface RequestService {
|
||||||
|
|
||||||
|
|
||||||
|
String request(String path, Object body);
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package tech.powerjob.client.service.impl;
|
||||||
|
|
||||||
|
import tech.powerjob.client.ClientConfig;
|
||||||
|
import tech.powerjob.client.module.AppAuthRequest;
|
||||||
|
import tech.powerjob.client.module.AppAuthResult;
|
||||||
|
import tech.powerjob.common.utils.DigestUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 封装鉴权相关逻辑
|
||||||
|
*
|
||||||
|
* @author tjq
|
||||||
|
* @since 2024/2/21
|
||||||
|
*/
|
||||||
|
abstract class AppAuthClusterRequestService extends ClusterRequestService {
|
||||||
|
|
||||||
|
protected AppAuthResult appAuthResult;
|
||||||
|
|
||||||
|
public AppAuthClusterRequestService(ClientConfig config) {
|
||||||
|
super(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void refreshAuthInfo() {
|
||||||
|
AppAuthRequest appAuthRequest = new AppAuthRequest();
|
||||||
|
appAuthRequest.setAppName(config.getAppName());
|
||||||
|
appAuthRequest.setEncryptedPassword(DigestUtils.md5(config.getPassword()));
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,123 @@
|
|||||||
|
package tech.powerjob.client.service.impl;
|
||||||
|
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import tech.powerjob.client.ClientConfig;
|
||||||
|
import tech.powerjob.client.service.RequestService;
|
||||||
|
import tech.powerjob.common.OpenAPIConstant;
|
||||||
|
import tech.powerjob.common.exception.PowerJobException;
|
||||||
|
import tech.powerjob.common.serialize.JsonUtils;
|
||||||
|
|
||||||
|
import javax.net.ssl.X509TrustManager;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 集群请求服务
|
||||||
|
* 封装网络相关通用逻辑
|
||||||
|
*
|
||||||
|
* @author tjq
|
||||||
|
* @since 2024/2/21
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
abstract class ClusterRequestService implements RequestService {
|
||||||
|
|
||||||
|
protected final ClientConfig config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前地址(上次请求成功的地址)
|
||||||
|
*/
|
||||||
|
protected String currentAddress;
|
||||||
|
/**
|
||||||
|
* 鉴权相关 headers
|
||||||
|
*/
|
||||||
|
protected Map<String, String> authHeaders = Maps.newHashMap();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 地址格式
|
||||||
|
* 协议://域名/OpenAPI/子路径
|
||||||
|
*/
|
||||||
|
protected static final String URL_PATTERN = "%s://%s%s%s";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认超时时间
|
||||||
|
*/
|
||||||
|
protected static final Integer DEFAULT_TIMEOUT_SECONDS = 2;
|
||||||
|
|
||||||
|
protected static final int HTTP_SUCCESS_CODE = 200;
|
||||||
|
|
||||||
|
public ClusterRequestService(ClientConfig config) {
|
||||||
|
this.config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract String sendHttpRequest(String url, String body) throws IOException;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String request(String path, Object obj) {
|
||||||
|
|
||||||
|
String body = obj instanceof String ? (String) obj : JsonUtils.toJSONStringUnsafe(obj);
|
||||||
|
|
||||||
|
List<String> addressList = config.getAddressList();
|
||||||
|
// 先尝试默认地址
|
||||||
|
String url = getUrl(path, currentAddress);
|
||||||
|
try {
|
||||||
|
String res = sendHttpRequest(url, body);
|
||||||
|
if (StringUtils.isNotEmpty(res)) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.warn("[ClusterRequestService] request url:{} failed, reason is {}.", url, e.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 失败,开始重试
|
||||||
|
for (String addr : addressList) {
|
||||||
|
if (Objects.equals(addr, currentAddress)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
url = getUrl(path, addr);
|
||||||
|
try {
|
||||||
|
String res = sendHttpRequest(url, body);
|
||||||
|
if (StringUtils.isNotEmpty(res)) {
|
||||||
|
log.warn("[ClusterRequestService] server change: from({}) -> to({}).", currentAddress, addr);
|
||||||
|
currentAddress = addr;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.warn("[ClusterRequestService] request url:{} failed, reason is {}.", url, e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.error("[ClusterRequestService] do post for path: {} failed because of no server available in {}.", path, addressList);
|
||||||
|
throw new PowerJobException("no server available when send post request");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 不验证证书
|
||||||
|
* X.509 是一个国际标准,定义了公钥证书的格式。这个标准是由国际电信联盟(ITU-T)制定的,用于公钥基础设施(PKI)中数字证书的创建和分发。X.509证书主要用于在公开网络上验证实体的身份,如服务器或客户端的身份验证过程中,确保通信双方是可信的。X.509证书广泛应用于多种安全协议中,包括SSL/TLS,它是实现HTTPS的基础。
|
||||||
|
*/
|
||||||
|
protected static class NoVerifyX509TrustManager implements X509TrustManager {
|
||||||
|
@Override
|
||||||
|
public void checkClientTrusted(X509Certificate[] arg0, String arg1) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void checkServerTrusted(X509Certificate[] arg0, String arg1) {
|
||||||
|
// 不验证
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public X509Certificate[] getAcceptedIssuers() {
|
||||||
|
return new X509Certificate[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private String getUrl(String path, String address) {
|
||||||
|
String protocol = config.getProtocol().getProtocol();
|
||||||
|
return String.format(URL_PATTERN, protocol, address, OpenAPIConstant.WEB_PATH, path);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,109 @@
|
|||||||
|
package tech.powerjob.client.service.impl;
|
||||||
|
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import okhttp3.*;
|
||||||
|
import tech.powerjob.client.ClientConfig;
|
||||||
|
import tech.powerjob.client.common.Protocol;
|
||||||
|
import tech.powerjob.common.OmsConstant;
|
||||||
|
import tech.powerjob.common.exception.PowerJobException;
|
||||||
|
|
||||||
|
import javax.net.ssl.*;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* desc
|
||||||
|
*
|
||||||
|
* @author tjq
|
||||||
|
* @since 2024/2/20
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class ClusterRequestServiceOkHttp3Impl extends ClusterRequestService {
|
||||||
|
|
||||||
|
private final OkHttpClient okHttpClient;
|
||||||
|
|
||||||
|
|
||||||
|
public ClusterRequestServiceOkHttp3Impl(ClientConfig config) {
|
||||||
|
super(config);
|
||||||
|
|
||||||
|
// 初始化 HTTP 客户端
|
||||||
|
if (Protocol.HTTPS.equals(config.getProtocol())) {
|
||||||
|
okHttpClient = initHttpsNoVerifyClient();
|
||||||
|
} else {
|
||||||
|
okHttpClient = initHttpClient();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String sendHttpRequest(String url, String payload) throws IOException {
|
||||||
|
|
||||||
|
// 公共 header
|
||||||
|
Map<String, String> headers = Maps.newHashMap();
|
||||||
|
if (config.getDefaultHeaders() != null) {
|
||||||
|
headers.putAll(config.getDefaultHeaders());
|
||||||
|
}
|
||||||
|
|
||||||
|
MediaType jsonType = MediaType.parse(OmsConstant.JSON_MEDIA_TYPE);
|
||||||
|
RequestBody requestBody = RequestBody.create(jsonType, payload);
|
||||||
|
Request request = new Request.Builder()
|
||||||
|
.post(requestBody)
|
||||||
|
.url(url)
|
||||||
|
.headers(Headers.of(headers))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
try (Response response = okHttpClient.newCall(request).execute()) {
|
||||||
|
int responseCode = response.code();
|
||||||
|
if (responseCode == HTTP_SUCCESS_CODE) {
|
||||||
|
ResponseBody body = response.body();
|
||||||
|
if (body == null) {
|
||||||
|
return null;
|
||||||
|
}else {
|
||||||
|
return body.string();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new PowerJobException(String.format("http request failed,code=%d", responseCode));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
private OkHttpClient initHttpClient() {
|
||||||
|
OkHttpClient.Builder okHttpBuilder = commonOkHttpBuilder();
|
||||||
|
return okHttpBuilder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
private OkHttpClient initHttpsNoVerifyClient() {
|
||||||
|
|
||||||
|
X509TrustManager trustManager = new NoVerifyX509TrustManager();
|
||||||
|
|
||||||
|
SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||||
|
sslContext.init(null, new TrustManager[]{trustManager}, new SecureRandom());
|
||||||
|
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
|
||||||
|
|
||||||
|
OkHttpClient.Builder okHttpBuilder = commonOkHttpBuilder();
|
||||||
|
|
||||||
|
// 不需要校验证书
|
||||||
|
okHttpBuilder.sslSocketFactory(sslSocketFactory, trustManager);
|
||||||
|
// 不校验 url中的 hostname
|
||||||
|
okHttpBuilder.hostnameVerifier((String hostname, SSLSession session) -> true);
|
||||||
|
|
||||||
|
|
||||||
|
return okHttpBuilder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private OkHttpClient.Builder commonOkHttpBuilder() {
|
||||||
|
return new OkHttpClient.Builder()
|
||||||
|
// 设置读取超时时间
|
||||||
|
.readTimeout(Optional.ofNullable(config.getReadTimeout()).orElse(DEFAULT_TIMEOUT_SECONDS), TimeUnit.SECONDS)
|
||||||
|
// 设置写的超时时间
|
||||||
|
.writeTimeout(Optional.ofNullable(config.getReadTimeout()).orElse(DEFAULT_TIMEOUT_SECONDS), TimeUnit.SECONDS)
|
||||||
|
// 设置连接超时时间
|
||||||
|
.connectTimeout(Optional.ofNullable(config.getReadTimeout()).orElse(DEFAULT_TIMEOUT_SECONDS), TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -16,6 +16,8 @@ public class OpenAPIConstant {
|
|||||||
|
|
||||||
public static final String ASSERT = "/assert";
|
public static final String ASSERT = "/assert";
|
||||||
|
|
||||||
|
public static final String AUTH_APP = "/authApp";
|
||||||
|
|
||||||
/* ************* JOB 区 ************* */
|
/* ************* JOB 区 ************* */
|
||||||
|
|
||||||
public static final String SAVE_JOB = "/saveJob";
|
public static final String SAVE_JOB = "/saveJob";
|
||||||
@ -56,4 +58,10 @@ public class OpenAPIConstant {
|
|||||||
public static final String RETRY_WORKFLOW_INSTANCE = "/retryWfInstance";
|
public static final String RETRY_WORKFLOW_INSTANCE = "/retryWfInstance";
|
||||||
public static final String FETCH_WORKFLOW_INSTANCE_INFO = "/fetchWfInstanceInfo";
|
public static final String FETCH_WORKFLOW_INSTANCE_INFO = "/fetchWfInstanceInfo";
|
||||||
public static final String MARK_WORKFLOW_NODE_AS_SUCCESS = "/markWorkflowNodeAsSuccess";
|
public static final String MARK_WORKFLOW_NODE_AS_SUCCESS = "/markWorkflowNodeAsSuccess";
|
||||||
|
|
||||||
|
/* ************* 鉴权 ************* */
|
||||||
|
|
||||||
|
public static final String HEADER_ACCESS_TOKEN = "X-POWERJOB-ACCESS-TOKEN";
|
||||||
|
|
||||||
|
public static final String HEADER_APP_ID = "X-POWERJOB-APP-ID";
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,37 @@
|
|||||||
|
package tech.powerjob.common.response;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新的 Result,带状态码
|
||||||
|
*
|
||||||
|
* @author 程序帕鲁
|
||||||
|
* @since 2024/2/19
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class PowerResultDTO<T> extends ResultDTO<T> {
|
||||||
|
|
||||||
|
private String code;
|
||||||
|
|
||||||
|
public static <T> PowerResultDTO<T> s(T data) {
|
||||||
|
PowerResultDTO<T> r = new PowerResultDTO<>();
|
||||||
|
r.success = true;
|
||||||
|
r.data = data;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> PowerResultDTO<T> f(String message) {
|
||||||
|
PowerResultDTO<T> r = new PowerResultDTO<>();
|
||||||
|
r.success = false;
|
||||||
|
r.message = message;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> PowerResultDTO<T> f(Throwable t) {
|
||||||
|
return f(ExceptionUtils.getStackTrace(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -72,8 +72,9 @@ public class JsonUtils {
|
|||||||
try {
|
try {
|
||||||
return JSON_MAPPER.writeValueAsString(obj);
|
return JSON_MAPPER.writeValueAsString(obj);
|
||||||
}catch (Exception e) {
|
}catch (Exception e) {
|
||||||
throw new PowerJobException(e);
|
ExceptionUtils.rethrow(e);
|
||||||
}
|
}
|
||||||
|
throw new ImpossibleException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] toBytes(Object obj) {
|
public static byte[] toBytes(Object obj) {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package tech.powerjob.server.common.utils;
|
package tech.powerjob.common.utils;
|
||||||
|
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
@ -20,6 +21,11 @@ public class DigestUtils {
|
|||||||
*/
|
*/
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public static String md5(String input) {
|
public static String md5(String input) {
|
||||||
|
|
||||||
|
if (StringUtils.isEmpty(input)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
MessageDigest md5 = MessageDigest.getInstance("MD5");
|
MessageDigest md5 = MessageDigest.getInstance("MD5");
|
||||||
md5.update(input.getBytes());
|
md5.update(input.getBytes());
|
||||||
byte[] byteArray = md5.digest();
|
byte[] byteArray = md5.digest();
|
@ -108,6 +108,12 @@
|
|||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>tech.powerjob</groupId>
|
||||||
|
<artifactId>powerjob-client</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- 存储扩展-MongoDB,未使用可移除 -->
|
<!-- 存储扩展-MongoDB,未使用可移除 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.mongodb</groupId>
|
<groupId>org.mongodb</groupId>
|
||||||
|
@ -33,6 +33,8 @@ public enum AuthErrorCode {
|
|||||||
|
|
||||||
INVALID_TOKEN("-401", "INVALID_TOKEN"),
|
INVALID_TOKEN("-401", "INVALID_TOKEN"),
|
||||||
|
|
||||||
|
OPEN_API_AUTH_FAILED("-1001", "OPEN_API_AUTH_FAILED"),
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
||||||
private final String code;
|
private final String code;
|
||||||
|
@ -5,7 +5,7 @@ import org.apache.commons.lang3.StringUtils;
|
|||||||
import org.springframework.core.env.Environment;
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import tech.powerjob.server.auth.jwt.SecretProvider;
|
import tech.powerjob.server.auth.jwt.SecretProvider;
|
||||||
import tech.powerjob.server.common.utils.DigestUtils;
|
import tech.powerjob.common.utils.DigestUtils;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ import tech.powerjob.server.auth.common.AuthErrorCode;
|
|||||||
import tech.powerjob.server.auth.common.PowerJobAuthException;
|
import tech.powerjob.server.auth.common.PowerJobAuthException;
|
||||||
import tech.powerjob.server.auth.login.*;
|
import tech.powerjob.server.auth.login.*;
|
||||||
import tech.powerjob.server.common.Loggers;
|
import tech.powerjob.server.common.Loggers;
|
||||||
import tech.powerjob.server.common.utils.DigestUtils;
|
import tech.powerjob.common.utils.DigestUtils;
|
||||||
import tech.powerjob.server.persistence.remote.model.PwjbUserInfoDO;
|
import tech.powerjob.server.persistence.remote.model.PwjbUserInfoDO;
|
||||||
import tech.powerjob.server.persistence.remote.repository.PwjbUserInfoRepository;
|
import tech.powerjob.server.persistence.remote.repository.PwjbUserInfoRepository;
|
||||||
|
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
package tech.powerjob.server.core.service;
|
package tech.powerjob.server.core.service;
|
||||||
|
|
||||||
|
import tech.powerjob.server.persistence.remote.model.AppInfoDO;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AppInfoService
|
* AppInfoService
|
||||||
*
|
*
|
||||||
@ -7,5 +11,21 @@ package tech.powerjob.server.core.service;
|
|||||||
* @since 2023/3/4
|
* @since 2023/3/4
|
||||||
*/
|
*/
|
||||||
public interface AppInfoService {
|
public interface AppInfoService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证 APP 账号密码
|
||||||
|
* @param appName 账号
|
||||||
|
* @param password 原文密码
|
||||||
|
* @return AppId
|
||||||
|
*/
|
||||||
Long assertApp(String appName, String password);
|
Long assertApp(String appName, String password);
|
||||||
|
|
||||||
|
Long assertAppWithEncryptedPassword(String appName, String encryptedPassword);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 AppInfo(带缓存)
|
||||||
|
* @param appId appId
|
||||||
|
* @return App 信息
|
||||||
|
*/
|
||||||
|
Optional<AppInfoDO> findByIdWithCache(Long appId);
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,19 @@
|
|||||||
package tech.powerjob.server.core.service.impl;
|
package tech.powerjob.server.core.service.impl;
|
||||||
|
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import tech.powerjob.common.exception.PowerJobException;
|
import tech.powerjob.common.exception.PowerJobException;
|
||||||
|
import tech.powerjob.common.utils.DigestUtils;
|
||||||
import tech.powerjob.server.core.service.AppInfoService;
|
import tech.powerjob.server.core.service.AppInfoService;
|
||||||
import tech.powerjob.server.persistence.remote.model.AppInfoDO;
|
import tech.powerjob.server.persistence.remote.model.AppInfoDO;
|
||||||
import tech.powerjob.server.persistence.remote.repository.AppInfoRepository;
|
import tech.powerjob.server.persistence.remote.repository.AppInfoRepository;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AppInfoServiceImpl
|
* AppInfoServiceImpl
|
||||||
@ -15,10 +21,17 @@ import java.util.Objects;
|
|||||||
* @author tjq
|
* @author tjq
|
||||||
* @since 2023/3/4
|
* @since 2023/3/4
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class AppInfoServiceImpl implements AppInfoService {
|
public class AppInfoServiceImpl implements AppInfoService {
|
||||||
|
|
||||||
|
private final Cache<Long, AppInfoDO> appId2AppInfoDO = CacheBuilder.newBuilder()
|
||||||
|
.softValues()
|
||||||
|
.expireAfterWrite(3, TimeUnit.MINUTES)
|
||||||
|
.maximumSize(1024)
|
||||||
|
.build();
|
||||||
|
|
||||||
private final AppInfoRepository appInfoRepository;
|
private final AppInfoRepository appInfoRepository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -36,4 +49,31 @@ public class AppInfoServiceImpl implements AppInfoService {
|
|||||||
}
|
}
|
||||||
throw new PowerJobException("password error!");
|
throw new PowerJobException("password error!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long assertAppWithEncryptedPassword(String appName, String encryptedPassword) {
|
||||||
|
AppInfoDO appInfo = appInfoRepository.findByAppName(appName).orElseThrow(() -> new PowerJobException("can't find appInfo by appName: " + appName));
|
||||||
|
if (Objects.equals(DigestUtils.md5(appInfo.getPassword()), encryptedPassword)) {
|
||||||
|
return appInfo.getId();
|
||||||
|
}
|
||||||
|
throw new PowerJobException("password error!");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<AppInfoDO> findByIdWithCache(Long appId) {
|
||||||
|
try {
|
||||||
|
AppInfoDO appInfoDO = appId2AppInfoDO.get(appId, () -> {
|
||||||
|
Optional<AppInfoDO> appInfoOpt = appInfoRepository.findById(appId);
|
||||||
|
if (appInfoOpt.isPresent()) {
|
||||||
|
return appInfoOpt.get();
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("can't find appInfo by appId:" + appId);
|
||||||
|
});
|
||||||
|
return Optional.of(appInfoDO);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("[AppInfoService] findByIdWithCache failed,appId={}", appId, e);
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -51,6 +51,11 @@
|
|||||||
<groupId>tech.powerjob</groupId>
|
<groupId>tech.powerjob</groupId>
|
||||||
<artifactId>powerjob-server-migrate</artifactId>
|
<artifactId>powerjob-server-migrate</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>tech.powerjob</groupId>
|
||||||
|
<artifactId>powerjob-client</artifactId>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<!-- SpringBoot maven plugin -->
|
<!-- SpringBoot maven plugin -->
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
package tech.powerjob.server.web.controller;
|
package tech.powerjob.server.openapi;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import tech.powerjob.client.module.AppAuthRequest;
|
||||||
|
import tech.powerjob.client.module.AppAuthResult;
|
||||||
import tech.powerjob.common.OpenAPIConstant;
|
import tech.powerjob.common.OpenAPIConstant;
|
||||||
import tech.powerjob.common.PowerQuery;
|
import tech.powerjob.common.PowerQuery;
|
||||||
import tech.powerjob.common.enums.InstanceStatus;
|
import tech.powerjob.common.enums.InstanceStatus;
|
||||||
@ -9,16 +11,14 @@ import tech.powerjob.common.request.http.SaveJobInfoRequest;
|
|||||||
import tech.powerjob.common.request.http.SaveWorkflowNodeRequest;
|
import tech.powerjob.common.request.http.SaveWorkflowNodeRequest;
|
||||||
import tech.powerjob.common.request.http.SaveWorkflowRequest;
|
import tech.powerjob.common.request.http.SaveWorkflowRequest;
|
||||||
import tech.powerjob.common.request.query.JobInfoQuery;
|
import tech.powerjob.common.request.query.JobInfoQuery;
|
||||||
import tech.powerjob.common.response.InstanceInfoDTO;
|
import tech.powerjob.common.response.*;
|
||||||
import tech.powerjob.common.response.JobInfoDTO;
|
|
||||||
import tech.powerjob.common.response.ResultDTO;
|
|
||||||
import tech.powerjob.common.response.WorkflowInstanceInfoDTO;
|
|
||||||
import tech.powerjob.server.core.instance.InstanceService;
|
import tech.powerjob.server.core.instance.InstanceService;
|
||||||
import tech.powerjob.server.core.service.AppInfoService;
|
import tech.powerjob.server.core.service.AppInfoService;
|
||||||
import tech.powerjob.server.core.service.CacheService;
|
import tech.powerjob.server.core.service.CacheService;
|
||||||
import tech.powerjob.server.core.service.JobService;
|
import tech.powerjob.server.core.service.JobService;
|
||||||
import tech.powerjob.server.core.workflow.WorkflowInstanceService;
|
import tech.powerjob.server.core.workflow.WorkflowInstanceService;
|
||||||
import tech.powerjob.server.core.workflow.WorkflowService;
|
import tech.powerjob.server.core.workflow.WorkflowService;
|
||||||
|
import tech.powerjob.server.openapi.security.OpenApiSecurityService;
|
||||||
import tech.powerjob.server.persistence.remote.model.WorkflowInfoDO;
|
import tech.powerjob.server.persistence.remote.model.WorkflowInfoDO;
|
||||||
import tech.powerjob.server.persistence.remote.model.WorkflowNodeInfoDO;
|
import tech.powerjob.server.persistence.remote.model.WorkflowNodeInfoDO;
|
||||||
import tech.powerjob.server.web.response.WorkflowInfoVO;
|
import tech.powerjob.server.web.response.WorkflowInfoVO;
|
||||||
@ -46,6 +46,8 @@ public class OpenAPIController {
|
|||||||
|
|
||||||
private final WorkflowInstanceService workflowInstanceService;
|
private final WorkflowInstanceService workflowInstanceService;
|
||||||
|
|
||||||
|
private final OpenApiSecurityService openApiSecurityService;
|
||||||
|
|
||||||
private final CacheService cacheService;
|
private final CacheService cacheService;
|
||||||
|
|
||||||
|
|
||||||
@ -54,6 +56,16 @@ public class OpenAPIController {
|
|||||||
return ResultDTO.success(appInfoService.assertApp(appName, password));
|
return ResultDTO.success(appInfoService.assertApp(appName, password));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* APP 鉴权
|
||||||
|
* @param appAuthRequest 鉴权请求
|
||||||
|
* @return 鉴权响应
|
||||||
|
*/
|
||||||
|
@PostMapping(OpenAPIConstant.AUTH_APP)
|
||||||
|
public PowerResultDTO<AppAuthResult> auth(@RequestBody AppAuthRequest appAuthRequest) {
|
||||||
|
return PowerResultDTO.s(openApiSecurityService.authAppByParam(appAuthRequest));
|
||||||
|
}
|
||||||
|
|
||||||
/* ************* Job 区 ************* */
|
/* ************* Job 区 ************* */
|
||||||
|
|
||||||
@PostMapping(OpenAPIConstant.SAVE_JOB)
|
@PostMapping(OpenAPIConstant.SAVE_JOB)
|
@ -0,0 +1,46 @@
|
|||||||
|
package tech.powerjob.server.openapi;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.lang.NonNull;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.servlet.HandlerInterceptor;
|
||||||
|
import tech.powerjob.server.openapi.security.OpenApiSecurityService;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OpenAPI 拦截器
|
||||||
|
*
|
||||||
|
* @author 程序帕鲁
|
||||||
|
* @since 2024/2/19
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
public class OpenApiInterceptor implements HandlerInterceptor {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private OpenApiSecurityService openApiSecurityService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 4.x 及前序版本的 OpenAPI 均为携带 auth 的必要参数,直接开启鉴权功能会导致之前的服务全部报错
|
||||||
|
* 因此提供功能开关给到使用者,若无安全影响,可展示关闭鉴权功能,等 client 升级完毕后再打开鉴权
|
||||||
|
*/
|
||||||
|
@Value("${oms.auth.openapi.enable:false}")
|
||||||
|
private boolean enableOpenApiAuth;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler) throws Exception {
|
||||||
|
|
||||||
|
if (!enableOpenApiAuth) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
openApiSecurityService.authAppByToken(request);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package tech.powerjob.server.openapi.security;
|
||||||
|
|
||||||
|
import tech.powerjob.client.module.AppAuthRequest;
|
||||||
|
import tech.powerjob.client.module.AppAuthResult;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OPENAPI 安全服务
|
||||||
|
*
|
||||||
|
* @author tjq
|
||||||
|
* @since 2024/2/19
|
||||||
|
*/
|
||||||
|
public interface OpenApiSecurityService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* APP 纬度请求的鉴权 & 验证
|
||||||
|
* @param appAuthRequest 请求参数
|
||||||
|
* @return token
|
||||||
|
*/
|
||||||
|
AppAuthResult authAppByParam(AppAuthRequest appAuthRequest);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* APP 纬度请求的鉴权 & 验证
|
||||||
|
* @param httpServletRequest http 原始请求
|
||||||
|
*/
|
||||||
|
void authAppByToken(HttpServletRequest httpServletRequest);
|
||||||
|
}
|
@ -0,0 +1,98 @@
|
|||||||
|
package tech.powerjob.server.openapi.security;
|
||||||
|
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.collections4.MapUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import tech.powerjob.client.module.AppAuthRequest;
|
||||||
|
import tech.powerjob.client.module.AppAuthResult;
|
||||||
|
import tech.powerjob.common.OpenAPIConstant;
|
||||||
|
import tech.powerjob.server.auth.common.AuthErrorCode;
|
||||||
|
import tech.powerjob.server.auth.common.PowerJobAuthException;
|
||||||
|
import tech.powerjob.server.auth.common.utils.HttpServletUtils;
|
||||||
|
import tech.powerjob.server.auth.jwt.JwtService;
|
||||||
|
import tech.powerjob.common.utils.DigestUtils;
|
||||||
|
import tech.powerjob.server.core.service.AppInfoService;
|
||||||
|
import tech.powerjob.server.persistence.remote.model.AppInfoDO;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OpenApiSecurityService
|
||||||
|
*
|
||||||
|
* @author tjq
|
||||||
|
* @since 2024/2/19
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class OpenApiSecurityServiceImpl implements OpenApiSecurityService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private JwtService jwtService;
|
||||||
|
@Resource
|
||||||
|
private AppInfoService appInfoService;
|
||||||
|
|
||||||
|
private static final String JWT_KEY_APP_ID = "appId";
|
||||||
|
private static final String JWT_KEY_APP_PASSWORD = "password";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void authAppByToken(HttpServletRequest httpServletRequest) {
|
||||||
|
|
||||||
|
String token = HttpServletUtils.fetchFromHeader(OpenAPIConstant.HEADER_ACCESS_TOKEN, httpServletRequest);
|
||||||
|
String appIdFromHeader = HttpServletUtils.fetchFromHeader(OpenAPIConstant.HEADER_APP_ID, httpServletRequest);
|
||||||
|
|
||||||
|
if (StringUtils.isEmpty(appIdFromHeader)) {
|
||||||
|
throw new IllegalArgumentException("can't find appId in HTTP header");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StringUtils.isEmpty(token)) {
|
||||||
|
throw new PowerJobAuthException(AuthErrorCode.OPEN_API_AUTH_FAILED);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> jwtResult = jwtService.parse(token, null);
|
||||||
|
|
||||||
|
Long appIdFromJwt = MapUtils.getLong(jwtResult, JWT_KEY_APP_ID);
|
||||||
|
String passwordFromJwt = MapUtils.getString(jwtResult, JWT_KEY_APP_PASSWORD);
|
||||||
|
|
||||||
|
// 校验 appId 一致性
|
||||||
|
if (!StringUtils.equals(appIdFromHeader, String.valueOf(appIdFromJwt))) {
|
||||||
|
throw new IllegalArgumentException("Inconsistent appId from header and token");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 此处不考虑改密码后的缓存时间,毕竟只要改了密码,一定会报错。换言之 OpenAPI 模式下,密码不可更改
|
||||||
|
Optional<AppInfoDO> appInfoOpt = appInfoService.findByIdWithCache(appIdFromJwt);
|
||||||
|
if (!appInfoOpt.isPresent()) {
|
||||||
|
throw new IllegalArgumentException("can't find app by appId: " + appIdFromJwt);
|
||||||
|
}
|
||||||
|
|
||||||
|
String dbOriginPassword = appInfoOpt.get().getPassword();
|
||||||
|
if (!StringUtils.equals(passwordFromJwt, DigestUtils.md5(dbOriginPassword))) {
|
||||||
|
throw new PowerJobAuthException(AuthErrorCode.OPEN_API_AUTH_FAILED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AppAuthResult authAppByParam(AppAuthRequest appAuthRequest) {
|
||||||
|
|
||||||
|
String appName = appAuthRequest.getAppName();
|
||||||
|
String encryptedPassword = appAuthRequest.getEncryptedPassword();
|
||||||
|
|
||||||
|
Long appId = appInfoService.assertAppWithEncryptedPassword(appName, encryptedPassword);
|
||||||
|
|
||||||
|
Map<String, Object> jwtBody = Maps.newHashMap();
|
||||||
|
jwtBody.put(JWT_KEY_APP_ID, appId);
|
||||||
|
jwtBody.put(JWT_KEY_APP_PASSWORD, encryptedPassword);
|
||||||
|
|
||||||
|
AppAuthResult appAuthResult = new AppAuthResult();
|
||||||
|
|
||||||
|
appAuthResult.setAppId(appId);
|
||||||
|
appAuthResult.setToken(jwtService.build(jwtBody, null));
|
||||||
|
|
||||||
|
return appAuthResult;
|
||||||
|
}
|
||||||
|
}
|
@ -9,8 +9,7 @@ import org.springframework.web.bind.annotation.ControllerAdvice;
|
|||||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
import tech.powerjob.common.exception.PowerJobException;
|
import tech.powerjob.common.exception.PowerJobException;
|
||||||
import tech.powerjob.common.response.ResultDTO;
|
import tech.powerjob.common.response.PowerResultDTO;
|
||||||
import tech.powerjob.server.web.response.WebResultDTO;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 统一处理 web 层异常信息
|
* 统一处理 web 层异常信息
|
||||||
@ -24,9 +23,9 @@ public class ControllerExceptionHandler {
|
|||||||
|
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
@ExceptionHandler(Exception.class)
|
@ExceptionHandler(Exception.class)
|
||||||
public WebResultDTO<Void> exceptionHandler(Exception e) {
|
public PowerResultDTO<Void> exceptionHandler(Exception e) {
|
||||||
|
|
||||||
WebResultDTO<Void> ret = new WebResultDTO<>(ResultDTO.failed(ExceptionUtils.getMessage(e)));
|
PowerResultDTO<Void> ret = PowerResultDTO.f(ExceptionUtils.getMessage(e));
|
||||||
|
|
||||||
// 不是所有异常都需要打印完整堆栈,后续可以定义内部的Exception,便于判断
|
// 不是所有异常都需要打印完整堆栈,后续可以定义内部的Exception,便于判断
|
||||||
if (e instanceof PowerJobException) {
|
if (e instanceof PowerJobException) {
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
package tech.powerjob.server.web.response;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import tech.powerjob.common.response.ResultDTO;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* WEB 请求结果
|
|
||||||
*
|
|
||||||
* @author tjq
|
|
||||||
* @since 2024/2/18
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
public class WebResultDTO<T> extends ResultDTO<T> {
|
|
||||||
|
|
||||||
private String code;
|
|
||||||
|
|
||||||
public WebResultDTO() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public WebResultDTO(ResultDTO<T> res) {
|
|
||||||
this.success = res.isSuccess();
|
|
||||||
this.data = res.getData();
|
|
||||||
this.message = res.getMessage();
|
|
||||||
}
|
|
||||||
}
|
|
@ -8,7 +8,7 @@ import tech.powerjob.common.serialize.JsonUtils;
|
|||||||
import tech.powerjob.common.utils.CommonUtils;
|
import tech.powerjob.common.utils.CommonUtils;
|
||||||
import tech.powerjob.server.auth.common.AuthErrorCode;
|
import tech.powerjob.server.auth.common.AuthErrorCode;
|
||||||
import tech.powerjob.server.auth.common.PowerJobAuthException;
|
import tech.powerjob.server.auth.common.PowerJobAuthException;
|
||||||
import tech.powerjob.server.common.utils.DigestUtils;
|
import tech.powerjob.common.utils.DigestUtils;
|
||||||
import tech.powerjob.server.persistence.remote.model.PwjbUserInfoDO;
|
import tech.powerjob.server.persistence.remote.model.PwjbUserInfoDO;
|
||||||
import tech.powerjob.server.persistence.remote.repository.PwjbUserInfoRepository;
|
import tech.powerjob.server.persistence.remote.repository.PwjbUserInfoRepository;
|
||||||
import tech.powerjob.server.web.request.ChangePasswordRequest;
|
import tech.powerjob.server.web.request.ChangePasswordRequest;
|
||||||
|
@ -23,3 +23,4 @@ oms.table-prefix=
|
|||||||
|
|
||||||
###### PowerJob User and Permission Configuration Configuration ######
|
###### PowerJob User and Permission Configuration Configuration ######
|
||||||
oms.auth.initiliaze.admin.password=powerjob_admin
|
oms.auth.initiliaze.admin.password=powerjob_admin
|
||||||
|
oms.auth.openapi.enable=false
|
Loading…
x
Reference in New Issue
Block a user