1. iwork 二次适配

This commit is contained in:
chenbowen
2025-11-21 18:20:11 +08:00
parent 7e3baeba46
commit ce39dc6d4b
10 changed files with 243 additions and 52 deletions

View File

@@ -1,6 +1,10 @@
package com.zt.plat.module.system.controller.admin.integration.iwork; package com.zt.plat.module.system.controller.admin.integration.iwork;
import com.zt.plat.framework.common.pojo.CommonResult; import com.zt.plat.framework.common.pojo.CommonResult;
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkAuthRegisterReqVO;
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkAuthRegisterRespVO;
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkAuthTokenReqVO;
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkAuthTokenRespVO;
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkDepartmentQueryReqVO; import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkDepartmentQueryReqVO;
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkJobTitleQueryReqVO; import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkJobTitleQueryReqVO;
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkOperationRespVO; import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkOperationRespVO;
@@ -39,6 +43,18 @@ public class IWorkIntegrationController {
private final IWorkIntegrationService integrationService; private final IWorkIntegrationService integrationService;
private final IWorkOrgRestService orgRestService; private final IWorkOrgRestService orgRestService;
@PostMapping("/auth/register")
@Operation(summary = "注册 iWork 凭证,获取服务端公钥与 secret")
public CommonResult<IWorkAuthRegisterRespVO> register(@Valid @RequestBody IWorkAuthRegisterReqVO reqVO) {
return success(integrationService.registerSession(reqVO));
}
@PostMapping("/auth/token")
@Operation(summary = "申请 iWork Token独立接口")
public CommonResult<IWorkAuthTokenRespVO> acquireToken(@Valid @RequestBody IWorkAuthTokenReqVO reqVO) {
return success(integrationService.acquireToken(reqVO));
}
@PostMapping("/user/resolve") @PostMapping("/user/resolve")
@Operation(summary = "根据外部标识获取 iWork 用户编号") @Operation(summary = "根据外部标识获取 iWork 用户编号")
public CommonResult<IWorkUserInfoRespVO> resolveUser(@Valid @RequestBody IWorkUserInfoReqVO reqVO) { public CommonResult<IWorkUserInfoRespVO> resolveUser(@Valid @RequestBody IWorkUserInfoReqVO reqVO) {

View File

@@ -0,0 +1,14 @@
package com.zt.plat.module.system.controller.admin.integration.iwork.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 请求重新向 iWork 注册以换取服务端公钥与 secret。
*/
@Data
public class IWorkAuthRegisterReqVO {
@Schema(description = "是否强制刷新注册信息", example = "false")
private Boolean forceRefreshRegistration;
}

View File

@@ -0,0 +1,26 @@
package com.zt.plat.module.system.controller.admin.integration.iwork.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 返回 iWork 注册后的公钥与密钥信息。
*/
@Data
public class IWorkAuthRegisterRespVO {
@Schema(description = "使用的 iWork 应用编号", example = "iwork-app")
private String appId;
@Schema(description = "本地配置的客户端公钥Base64")
private String clientPublicKey;
@Schema(description = "自动生成的客户端私钥Base64仅在未配置固定公钥时返回")
private String clientPrivateKey;
@Schema(description = "iWork 返回的 server public keyBase64")
private String serverPublicKey;
@Schema(description = "iWork 返回的 secret用于后续申请 token")
private String secret;
}

View File

@@ -0,0 +1,16 @@
package com.zt.plat.module.system.controller.admin.integration.iwork.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 申请 iWork token 的请求参数。
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class IWorkAuthTokenReqVO extends IWorkBaseReqVO {
@Schema(description = "是否强制重新执行注册流程")
private Boolean forceRefreshRegistration;
}

View File

@@ -0,0 +1,29 @@
package com.zt.plat.module.system.controller.admin.integration.iwork.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 申请 token 的返回结果。
*/
@Data
public class IWorkAuthTokenRespVO {
@Schema(description = "使用的 iWork appId", example = "iwork-app")
private String appId;
@Schema(description = "作为操作人的 iWork 用户编号", example = "1")
private String operatorUserId;
@Schema(description = "iWork 返回的访问 token")
private String token;
@Schema(description = "与 token 匹配的加密 userId供 header 直接使用")
private String encryptedUserId;
@Schema(description = "token 预计过期时间Epoch 秒)")
private Long expiresAtEpochSecond;
@Schema(description = "当前会话对应的 server public key")
private String serverPublicKey;
}

View File

@@ -85,12 +85,12 @@ public class IWorkProperties {
@Getter @Getter
public static class Headers { public static class Headers {
private final String appId = "app-id"; private final String appId = "appid";
private final String clientPublicKey = "client-public-key"; private final String clientPublicKey = "cpk";
private final String secret = "secret"; private final String secret = "secret";
private final String token = "token"; private final String token = "token";
private final String time = "time"; private final String time = "time";
private final String userId = "user-id"; private final String userId = "userid";
} }
@Data @Data

View File

@@ -9,7 +9,7 @@ public interface IWorkIntegrationErrorCodeConstants {
ErrorCode IWORK_BASE_URL_MISSING = new ErrorCode(1_010_200_001, "iWork 集成未配置网关地址"); ErrorCode IWORK_BASE_URL_MISSING = new ErrorCode(1_010_200_001, "iWork 集成未配置网关地址");
ErrorCode IWORK_CONFIGURATION_INVALID = new ErrorCode(1_010_200_002, ErrorCode IWORK_CONFIGURATION_INVALID = new ErrorCode(1_010_200_002,
"iWork 集成缺少必填配置appId/clientPublicKey/userId/workflowId"); "iWork 集成缺少必填配置appId/userId/workflowId或配置无效");
ErrorCode IWORK_REGISTER_FAILED = new ErrorCode(1_010_200_003, "iWork 注册授权失败"); ErrorCode IWORK_REGISTER_FAILED = new ErrorCode(1_010_200_003, "iWork 注册授权失败");
ErrorCode IWORK_APPLY_TOKEN_FAILED = new ErrorCode(1_010_200_004, "iWork 令牌申请失败"); ErrorCode IWORK_APPLY_TOKEN_FAILED = new ErrorCode(1_010_200_004, "iWork 令牌申请失败");
ErrorCode IWORK_REMOTE_REQUEST_FAILED = new ErrorCode(1_010_200_005, "iWork 接口请求失败"); ErrorCode IWORK_REMOTE_REQUEST_FAILED = new ErrorCode(1_010_200_005, "iWork 接口请求失败");

View File

@@ -1,5 +1,9 @@
package com.zt.plat.module.system.service.integration.iwork; package com.zt.plat.module.system.service.integration.iwork;
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkAuthRegisterReqVO;
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkAuthRegisterRespVO;
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkAuthTokenReqVO;
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkAuthTokenRespVO;
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkOperationRespVO; import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkOperationRespVO;
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkUserInfoReqVO; import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkUserInfoReqVO;
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkUserInfoRespVO; import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkUserInfoRespVO;
@@ -11,6 +15,16 @@ import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkWork
*/ */
public interface IWorkIntegrationService { public interface IWorkIntegrationService {
/**
* 主动触发注册流程,获取 iWork 返回的服务端公钥与 secret。
*/
IWorkAuthRegisterRespVO registerSession(IWorkAuthRegisterReqVO reqVO);
/**
* 主动向 iWork 申请访问 token并返回相关会话信息。
*/
IWorkAuthTokenRespVO acquireToken(IWorkAuthTokenReqVO reqVO);
/** /**
* 根据外部标识解析 iWork 内部用户编号。 * 根据外部标识解析 iWork 内部用户编号。
*/ */

View File

@@ -9,27 +9,14 @@ import com.github.benmanes.caffeine.cache.Caffeine;
import com.zt.plat.framework.common.exception.ErrorCode; import com.zt.plat.framework.common.exception.ErrorCode;
import com.zt.plat.framework.common.exception.ServiceException; import com.zt.plat.framework.common.exception.ServiceException;
import com.zt.plat.framework.common.exception.util.ServiceExceptionUtil; import com.zt.plat.framework.common.exception.util.ServiceExceptionUtil;
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkDetailRecordVO; import com.zt.plat.module.system.controller.admin.integration.iwork.vo.*;
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkDetailTableVO;
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkFormFieldVO;
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkOperationRespVO;
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkUserInfoReqVO;
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkUserInfoRespVO;
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkWorkflowCreateReqVO;
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkWorkflowVoidReqVO;
import com.zt.plat.module.system.framework.integration.iwork.config.IWorkProperties; import com.zt.plat.module.system.framework.integration.iwork.config.IWorkProperties;
import com.zt.plat.module.system.service.integration.iwork.IWorkIntegrationService; import com.zt.plat.module.system.service.integration.iwork.IWorkIntegrationService;
import lombok.Getter; import lombok.Getter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.ToString; import lombok.ToString;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import okhttp3.FormBody; import okhttp3.*;
import okhttp3.Headers;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.LinkedMultiValueMap;
@@ -39,16 +26,10 @@ import org.springframework.util.StringUtils;
import javax.crypto.Cipher; import javax.crypto.Cipher;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.security.KeyFactory; import java.security.*;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec; import java.security.spec.X509EncodedKeySpec;
import java.time.Instant; import java.time.Instant;
import java.util.Base64; import java.util.*;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import static com.zt.plat.module.system.service.integration.iwork.IWorkIntegrationErrorCodeConstants.*; import static com.zt.plat.module.system.service.integration.iwork.IWorkIntegrationErrorCodeConstants.*;
@@ -71,21 +52,68 @@ public class IWorkIntegrationServiceImpl implements IWorkIntegrationService {
.maximumSize(256) .maximumSize(256)
.build(); .build();
private final Cache<String, PublicKey> publicKeyCache = Caffeine.newBuilder() private final Cache<String, RegistrationState> registrationCache = Caffeine.newBuilder()
.maximumSize(32)
.build();
private final Cache<String, ClientKeyPair> clientKeyCache = Caffeine.newBuilder()
.maximumSize(32)
.build();
private final Cache<String, PublicKey> publicKeyCache = Caffeine.newBuilder()
.maximumSize(64) .maximumSize(64)
.build(); .build();
private volatile OkHttpClient cachedHttpClient; private volatile OkHttpClient cachedHttpClient;
@Override
public IWorkAuthRegisterRespVO registerSession(IWorkAuthRegisterReqVO reqVO) {
assertConfigured();
String appId = resolveAppId();
boolean forceRefresh = reqVO != null && Boolean.TRUE.equals(reqVO.getForceRefreshRegistration());
ClientKeyPair clientKeyPair = resolveClientKeyPair(appId, forceRefresh);
RegistrationState registration = obtainRegistration(appId, clientKeyPair, forceRefresh);
IWorkAuthRegisterRespVO respVO = new IWorkAuthRegisterRespVO();
respVO.setAppId(appId);
respVO.setClientPublicKey(clientKeyPair.publicKey());
respVO.setClientPrivateKey(clientKeyPair.privateKey());
respVO.setServerPublicKey(registration.spk());
respVO.setSecret(registration.secret());
return respVO;
}
@Override
public IWorkAuthTokenRespVO acquireToken(IWorkAuthTokenReqVO reqVO) {
assertConfigured();
String appId = resolveAppId();
String operatorUserId = resolveOperatorUserId(reqVO.getOperatorUserId());
boolean forceRegistration = Boolean.TRUE.equals(reqVO.getForceRefreshRegistration());
boolean forceToken = Boolean.TRUE.equals(reqVO.getForceRefreshToken());
boolean force = forceRegistration || forceToken;
ClientKeyPair clientKeyPair = resolveClientKeyPair(appId, forceRegistration);
IWorkSession session = ensureSession(appId, clientKeyPair, operatorUserId, force);
IWorkAuthTokenRespVO respVO = new IWorkAuthTokenRespVO();
respVO.setAppId(appId);
respVO.setOperatorUserId(operatorUserId);
respVO.setToken(session.getToken());
respVO.setEncryptedUserId(session.getEncryptedUserId());
respVO.setExpiresAtEpochSecond(session.getExpiresAt().getEpochSecond());
respVO.setServerPublicKey(session.getSpk());
return respVO;
}
@Override @Override
public IWorkUserInfoRespVO resolveUserId(IWorkUserInfoReqVO reqVO) { public IWorkUserInfoRespVO resolveUserId(IWorkUserInfoReqVO reqVO) {
assertConfigured(); assertConfigured();
String appId = resolveAppId(); String appId = resolveAppId();
String clientPublicKey = resolveClientPublicKey(); ClientKeyPair clientKeyPair = resolveClientKeyPair(appId, Boolean.TRUE.equals(reqVO.getForceRefreshToken()));
String operatorUserId = resolveOperatorUserId(reqVO.getOperatorUserId()); String operatorUserId = resolveOperatorUserId(reqVO.getOperatorUserId());
ensureIdentifier(reqVO.getIdentifierKey(), reqVO.getIdentifierValue()); ensureIdentifier(reqVO.getIdentifierKey(), reqVO.getIdentifierValue());
IWorkSession session = ensureSession(appId, clientPublicKey, operatorUserId, Boolean.TRUE.equals(reqVO.getForceRefreshToken())); IWorkSession session = ensureSession(appId, clientKeyPair, operatorUserId, Boolean.TRUE.equals(reqVO.getForceRefreshToken()));
Map<String, Object> payload = buildUserPayload(reqVO); Map<String, Object> payload = buildUserPayload(reqVO);
String responseBody = executeJsonRequest(properties.getPaths().getUserInfo(), reqVO.getQueryParams(), appId, session, payload); String responseBody = executeJsonRequest(properties.getPaths().getUserInfo(), reqVO.getQueryParams(), appId, session, payload);
@@ -96,9 +124,9 @@ public class IWorkIntegrationServiceImpl implements IWorkIntegrationService {
public IWorkOperationRespVO createWorkflow(IWorkWorkflowCreateReqVO reqVO) { public IWorkOperationRespVO createWorkflow(IWorkWorkflowCreateReqVO reqVO) {
assertConfigured(); assertConfigured();
String appId = resolveAppId(); String appId = resolveAppId();
String clientPublicKey = resolveClientPublicKey(); ClientKeyPair clientKeyPair = resolveClientKeyPair(appId, Boolean.TRUE.equals(reqVO.getForceRefreshToken()));
String operatorUserId = resolveOperatorUserId(reqVO.getOperatorUserId()); String operatorUserId = resolveOperatorUserId(reqVO.getOperatorUserId());
IWorkSession session = ensureSession(appId, clientPublicKey, operatorUserId, Boolean.TRUE.equals(reqVO.getForceRefreshToken())); IWorkSession session = ensureSession(appId, clientKeyPair, operatorUserId, Boolean.TRUE.equals(reqVO.getForceRefreshToken()));
MultiValueMap<String, String> formData = buildCreateForm(reqVO); MultiValueMap<String, String> formData = buildCreateForm(reqVO);
appendFormExtras(formData, reqVO.getFormExtras()); appendFormExtras(formData, reqVO.getFormExtras());
@@ -110,12 +138,12 @@ public class IWorkIntegrationServiceImpl implements IWorkIntegrationService {
public IWorkOperationRespVO voidWorkflow(IWorkWorkflowVoidReqVO reqVO) { public IWorkOperationRespVO voidWorkflow(IWorkWorkflowVoidReqVO reqVO) {
assertConfigured(); assertConfigured();
String appId = resolveAppId(); String appId = resolveAppId();
String clientPublicKey = resolveClientPublicKey(); ClientKeyPair clientKeyPair = resolveClientKeyPair(appId, Boolean.TRUE.equals(reqVO.getForceRefreshToken()));
String operatorUserId = resolveOperatorUserId(reqVO.getOperatorUserId()); String operatorUserId = resolveOperatorUserId(reqVO.getOperatorUserId());
if (!StringUtils.hasText(reqVO.getRequestId())) { if (!StringUtils.hasText(reqVO.getRequestId())) {
throw ServiceExceptionUtil.exception(IWORK_USER_IDENTIFIER_MISSING); throw ServiceExceptionUtil.exception(IWORK_USER_IDENTIFIER_MISSING);
} }
IWorkSession session = ensureSession(appId, clientPublicKey, operatorUserId, Boolean.TRUE.equals(reqVO.getForceRefreshToken())); IWorkSession session = ensureSession(appId, clientKeyPair, operatorUserId, Boolean.TRUE.equals(reqVO.getForceRefreshToken()));
MultiValueMap<String, String> formData = buildVoidForm(reqVO); MultiValueMap<String, String> formData = buildVoidForm(reqVO);
appendFormExtras(formData, reqVO.getFormExtras()); appendFormExtras(formData, reqVO.getFormExtras());
@@ -127,7 +155,7 @@ public class IWorkIntegrationServiceImpl implements IWorkIntegrationService {
if (!StringUtils.hasText(properties.getBaseUrl())) { if (!StringUtils.hasText(properties.getBaseUrl())) {
throw ServiceExceptionUtil.exception(IWORK_BASE_URL_MISSING); throw ServiceExceptionUtil.exception(IWORK_BASE_URL_MISSING);
} }
if (!StringUtils.hasText(properties.getAppId()) || !StringUtils.hasText(properties.getClientPublicKey())) { if (!StringUtils.hasText(properties.getAppId())) {
throw ServiceExceptionUtil.exception(IWORK_CONFIGURATION_INVALID); throw ServiceExceptionUtil.exception(IWORK_CONFIGURATION_INVALID);
} }
} }
@@ -150,12 +178,33 @@ public class IWorkIntegrationServiceImpl implements IWorkIntegrationService {
return StringUtils.trimWhitespace(value); return StringUtils.trimWhitespace(value);
} }
private String resolveClientPublicKey() { private ClientKeyPair resolveClientKeyPair(String appId, boolean forceRefresh) {
String value = properties.getClientPublicKey(); String configured = properties.getClientPublicKey();
if (!StringUtils.hasText(value)) { if (StringUtils.hasText(configured)) {
throw ServiceExceptionUtil.exception(IWORK_CONFIGURATION_INVALID); return new ClientKeyPair(StringUtils.trimWhitespace(configured), null);
}
if (!forceRefresh) {
ClientKeyPair cached = clientKeyCache.getIfPresent(appId);
if (cached != null) {
return cached;
}
}
ClientKeyPair generated = generateClientKeyPair();
clientKeyCache.put(appId, generated);
return generated;
}
private ClientKeyPair generateClientKeyPair() {
try {
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
generator.initialize(2048);
KeyPair pair = generator.generateKeyPair();
String publicKey = Base64.getEncoder().encodeToString(pair.getPublic().getEncoded());
String privateKey = Base64.getEncoder().encodeToString(pair.getPrivate().getEncoded());
return new ClientKeyPair(publicKey, privateKey);
} catch (NoSuchAlgorithmException ex) {
throw new ServiceException(IWORK_CONFIGURATION_INVALID.getCode(), "生成客户端 RSA 公钥失败: " + ex.getMessage());
} }
return StringUtils.trimWhitespace(value);
} }
private void ensureIdentifier(String identifierKey, String identifierValue) { private void ensureIdentifier(String identifierKey, String identifierValue) {
@@ -164,7 +213,7 @@ public class IWorkIntegrationServiceImpl implements IWorkIntegrationService {
} }
} }
private IWorkSession ensureSession(String appId, String clientPublicKey, String operatorUserId, boolean forceRefresh) { private IWorkSession ensureSession(String appId, ClientKeyPair clientKeyPair, String operatorUserId, boolean forceRefresh) {
SessionKey key = new SessionKey(appId, operatorUserId); SessionKey key = new SessionKey(appId, operatorUserId);
Instant now = Instant.now(); Instant now = Instant.now();
if (!forceRefresh) { if (!forceRefresh) {
@@ -178,14 +227,14 @@ public class IWorkIntegrationServiceImpl implements IWorkIntegrationService {
if (!forceRefresh && cached != null && cached.isValid(now, properties.getToken().getRefreshAheadSeconds())) { if (!forceRefresh && cached != null && cached.isValid(now, properties.getToken().getRefreshAheadSeconds())) {
return cached; return cached;
} }
IWorkSession session = createSession(appId, clientPublicKey, operatorUserId); IWorkSession session = createSession(appId, clientKeyPair, operatorUserId, forceRefresh);
sessionCache.put(key, session); sessionCache.put(key, session);
return session; return session;
} }
} }
private IWorkSession createSession(String appId, String clientPublicKey, String operatorUserId) { private IWorkSession createSession(String appId, ClientKeyPair clientKeyPair, String operatorUserId, boolean forceRefreshRegistration) {
RegistrationResult registration = register(appId, clientPublicKey); RegistrationState registration = obtainRegistration(appId, clientKeyPair, forceRefreshRegistration);
String encryptedSecret = encryptWithPublicKey(registration.secret(), registration.spk()); String encryptedSecret = encryptWithPublicKey(registration.secret(), registration.spk());
String encryptedUserId = encryptWithPublicKey(operatorUserId, registration.spk()); String encryptedUserId = encryptWithPublicKey(operatorUserId, registration.spk());
String token = applyToken(appId, encryptedSecret); String token = applyToken(appId, encryptedSecret);
@@ -193,11 +242,32 @@ public class IWorkIntegrationServiceImpl implements IWorkIntegrationService {
return new IWorkSession(token, encryptedUserId, expiresAt, registration.spk()); return new IWorkSession(token, encryptedUserId, expiresAt, registration.spk());
} }
private RegistrationResult register(String appId, String clientPublicKey) { private RegistrationState obtainRegistration(String appId, ClientKeyPair clientKeyPair, boolean forceRefresh) {
if (!forceRefresh) {
RegistrationState cached = registrationCache.getIfPresent(appId);
if (cached != null && Objects.equals(cached.clientKeyPair().publicKey(), clientKeyPair.publicKey())) {
return cached;
}
}
String lockKey = ("iwork-registration::" + appId).intern();
synchronized (lockKey) {
if (!forceRefresh) {
RegistrationState cached = registrationCache.getIfPresent(appId);
if (cached != null && Objects.equals(cached.clientKeyPair().publicKey(), clientKeyPair.publicKey())) {
return cached;
}
}
RegistrationState registration = register(appId, clientKeyPair);
registrationCache.put(appId, registration);
return registration;
}
}
private RegistrationState register(String appId, ClientKeyPair clientKeyPair) {
Request request = new Request.Builder() Request request = new Request.Builder()
.url(resolveUrl(properties.getPaths().getRegister())) .url(resolveUrl(properties.getPaths().getRegister()))
.header(properties.getHeaders().getAppId(), appId) .header(properties.getHeaders().getAppId(), appId)
.header(properties.getHeaders().getClientPublicKey(), clientPublicKey) .header(properties.getHeaders().getClientPublicKey(), clientKeyPair.publicKey())
.post(RequestBody.create(null, new byte[0])) .post(RequestBody.create(null, new byte[0]))
.build(); .build();
String responseBody = executeRequest(request, IWORK_REGISTER_FAILED); String responseBody = executeRequest(request, IWORK_REGISTER_FAILED);
@@ -207,7 +277,7 @@ public class IWorkIntegrationServiceImpl implements IWorkIntegrationService {
if (!StringUtils.hasText(secret) || !StringUtils.hasText(spk)) { if (!StringUtils.hasText(secret) || !StringUtils.hasText(spk)) {
throw ServiceExceptionUtil.exception(IWORK_REGISTER_FAILED, "返回缺少 secret 或 spk"); throw ServiceExceptionUtil.exception(IWORK_REGISTER_FAILED, "返回缺少 secret 或 spk");
} }
return new RegistrationResult(secret, spk); return new RegistrationState(secret, spk, clientKeyPair);
} }
private String applyToken(String appId, String encryptedSecret) { private String applyToken(String appId, String encryptedSecret) {
@@ -575,7 +645,10 @@ public class IWorkIntegrationServiceImpl implements IWorkIntegrationService {
} }
} }
private record RegistrationResult(String secret, String spk) { private record RegistrationState(String secret, String spk, ClientKeyPair clientKeyPair) {
}
private record ClientKeyPair(String publicKey, String privateKey) {
} }
@Getter @Getter

View File

@@ -107,10 +107,11 @@ easy-trans:
iwork: iwork:
base-url: http://172.16.36.233:8080 base-url: http://172.16.36.233:8080
app-id: # app-id: f47ac10b-58cc-4372-a567-0e02b2c3d479
app-id: f47ac10b-58cc-4372-a567-0e02b2c3d479
client-public-key: client-public-key:
user-id: user-id: 9869
workflow-id: workflow-id: 1753
paths: paths:
register: /api/ec/dev/auth/regist register: /api/ec/dev/auth/regist
apply-token: /api/ec/dev/auth/applytoken apply-token: /api/ec/dev/auth/applytoken
@@ -169,6 +170,8 @@ xxl:
job: job:
executor: executor:
appname: ${spring.application.name} # 执行器 AppName appname: ${spring.application.name} # 执行器 AppName
port: 0
ip: 172.16.234.132
logpath: ${user.home}/logs/xxl-job/${spring.application.name} # 执行器运行日志文件存储磁盘路径 logpath: ${user.home}/logs/xxl-job/${spring.application.name} # 执行器运行日志文件存储磁盘路径
accessToken: default_token # 执行器通讯TOKEN accessToken: default_token # 执行器通讯TOKEN