- * Use of this software is governed by the Commercial License Agreement - * obtained after purchasing a license from BladeX. - *
- * 1. This software is for development use only under a valid license - * from BladeX. - *
- * 2. Redistribution of this software's source code to any third party - * without a commercial license is strictly prohibited. - *
- * 3. Licensees may copyright their own code but cannot use segments - * from this software for such purposes. Copyright of this software - * remains with BladeX. - *
- * Using this software signifies agreement to this License, and the software - * must not be used for illegal purposes. - *
- * THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is - * not liable for any claims arising from secondary or illegal development. - *
- * Author: Chill Zhuang (bladejava@qq.com) - */ -package org.springblade.hcs.dto; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Data; - -import java.io.Serial; -import java.io.Serializable; - -/** - * 合同合规系统(HCS)OAuth2 取令牌返回结果(GET /authapi/getToken) - *
- * TODO 待联调确认:v4 文档未给出本接口响应字段示例,字段名按通用 OAuth2 惯例预置, - * 联调时以实际返回为准(设计文档 §3.2)。 - * - * @author Chill - */ -@Data -@JsonIgnoreProperties(ignoreUnknown = true) -public class HcsTokenVO implements Serializable { - @Serial - private static final long serialVersionUID = 1L; - /** - * 访问令牌,调用业务接口时追加到 URL 参数 access_token - */ - @JsonProperty("access_token") - private String accessToken; - /** - * 令牌类型 - */ - @JsonProperty("token_type") - private String tokenType; - /** - * 令牌有效期(毫秒) - */ - @JsonProperty("expires_in") - private Long expiresIn; -} diff --git a/blade-third-party-api/blade-hcs-api/src/main/java/org/springblade/hcs/feign/IHcsClient.java b/blade-third-party-api/blade-hcs-api/src/main/java/org/springblade/hcs/feign/IHcsClient.java index 7b4a0eb7..cff70f6a 100644 --- a/blade-third-party-api/blade-hcs-api/src/main/java/org/springblade/hcs/feign/IHcsClient.java +++ b/blade-third-party-api/blade-hcs-api/src/main/java/org/springblade/hcs/feign/IHcsClient.java @@ -56,10 +56,8 @@ import org.springblade.hcs.dto.HcsRiskQueryDTO; import org.springblade.hcs.dto.HcsRiskVO; import org.springblade.hcs.dto.HcsSpecPaySaveDTO; import org.springblade.hcs.dto.HcsTemplateVO; -import org.springblade.hcs.dto.HcsTokenVO; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.http.MediaType; -import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; @@ -67,7 +65,11 @@ import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.multipart.MultipartFile; /** - * 合同合规系统(HCS)接口(一期 24 个业务接口 + OAuth2 取令牌,D4) + * 合同合规系统(HCS)接口(一期 24 个业务接口,D4) + *
+ * v4 接口说明:认证统一由 {@link org.springblade.hcs.interceptor.HcsAuthInterceptor} 注入 + * Authorization + Key-Auth 两个静态请求头,不再调用 getToken 取令牌; + * 各接口路径可用 thirdParty.hcs.*Url 配置覆盖(默认值即 v4 文档路径)。 *
* 除附件上传(multipart/form-data)、附件下载(文件流)外均为 POST + application/json(UTF-8)。
* 业务成败以统一出参 {@link HcsResult#isSuccess()} 为准;
@@ -78,7 +80,6 @@ import org.springframework.web.multipart.MultipartFile;
@FeignClient(name = "HCS", url = "${thirdParty.hcs.baseUrl}", configuration = HcsFeignClientConfig.class)
public interface IHcsClient {
- String GET_TOKEN_URL = "${thirdParty.hcs.getTokenUrl:/authapi/getToken}";
String PROJECT_ADD_URL = "${thirdParty.hcs.projectAddUrl:/openapi/sys-modeling/apis/data/km-project1/V1/projectApproval/add}";
String PROJECT_UPDATE_URL = "${thirdParty.hcs.projectUpdateUrl:/openapi/sys-modeling/apis/data/km-project1/V1/projectApproval/update}";
String PROJECT_LIST_URL = "${thirdParty.hcs.projectListUrl:/openapi/sys-modeling/apis/data/km-project1/V1/projectApproval/list}";
@@ -104,16 +105,6 @@ public interface IHcsClient {
String INVOICE_REG_ADD_URL = "${thirdParty.hcs.invoiceRegAddUrl:/openapi/eop-data/eopDataInvoiceRegistrationOpen/add}";
String INVOICE_REG_UPDATE_URL = "${thirdParty.hcs.invoiceRegUpdateUrl:/openapi/eop-data/eopDataInvoiceRegistrationOpen/update}";
- /**
- * OAuth2 获取令牌(appKey/appSecret 走 URL 参数,D2)
- *
- * @param appKey 应用 appKey
- * @param appSecret 应用 appSecret
- * @return 令牌信息
- */
- @GetMapping(GET_TOKEN_URL)
- HcsResult
+ * 所有业务接口统一注入两个静态认证头,不再走 getToken/令牌缓存:
*
- * Use of this software is governed by the Commercial License Agreement
- * obtained after purchasing a license from BladeX.
- *
- * 1. This software is for development use only under a valid license
- * from BladeX.
- *
- * 2. Redistribution of this software's source code to any third party
- * without a commercial license is strictly prohibited.
- *
- * 3. Licensees may copyright their own code but cannot use segments
- * from this software for such purposes. Copyright of this software
- * remains with BladeX.
- *
- * Using this software signifies agreement to this License, and the software
- * must not be used for illegal purposes.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
- * not liable for any claims arising from secondary or illegal development.
- *
- * Author: Chill Zhuang (bladejava@qq.com)
- */
-package org.springblade.hcs.token;
-
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springblade.core.redis.cache.BladeRedis;
-import org.springblade.core.tool.utils.StringUtil;
-import org.springblade.hcs.config.HcsProperties;
-import org.springblade.hcs.constant.HcsConstant;
-import org.springblade.hcs.dto.HcsResult;
-import org.springblade.hcs.dto.HcsTokenVO;
-import org.springblade.hcs.exception.HcsException;
-import org.springblade.hcs.feign.IHcsClient;
-import org.springframework.stereotype.Service;
-
-import java.time.Duration;
-import java.util.Objects;
-
-/**
- * 合同合规系统(HCS)OAuth2 令牌服务(D2,照 BfiServiceImpl 惯例)
- *
- * GET /authapi/getToken(appKey/appSecret)→ access_token 存 Redis
- * (key {@link HcsConstant#HCS_TOKEN_CACHE_KEY},过期前留 120s 缓冲)。
- * 业务调用统一经 {@link #getAccessToken()} 取缓存令牌;
- * 401 时调用 {@link #refreshAccessToken()} 强制刷新一次后重放(D7,重试职责归扫描任务,此处仅刷新令牌)。
- * auth-type=basic 时不走本服务,由拦截器注入 Basic 认证头。
- *
- * @author Chill
- */
-@Slf4j
-@Service
-@RequiredArgsConstructor
-public class HcsTokenService {
-
- private final HcsProperties properties;
- private final IHcsClient client;
- private final BladeRedis bladeRedis;
-
- /**
- * 获取访问令牌:Redis 命中直接返回,未命中远端取令牌并缓存
- *
- * @return access_token
- */
- public String getAccessToken() {
- String token = bladeRedis.get(HcsConstant.HCS_TOKEN_CACHE_KEY);
- if (StringUtil.isNotBlank(token)) {
- return token;
- }
- return requestToken();
- }
-
- /**
- * 强制刷新访问令牌(401 时调用一次并重放请求)
- *
- * @return 新 access_token
- */
- public String refreshAccessToken() {
- log.info("强制刷新HCS令牌,清除本地缓存");
- bladeRedis.del(HcsConstant.HCS_TOKEN_CACHE_KEY);
- return requestToken();
- }
-
- /**
- * 远端取令牌并缓存
- *
- * @return access_token
- */
- private String requestToken() {
- if (StringUtil.isBlank(properties.getAppKey()) || StringUtil.isBlank(properties.getAppSecret())) {
- throw new HcsException("获取HCS令牌失败,appKey/appSecret 未配置(thirdParty.hcs.app-key/app-secret)");
- }
- long start = System.currentTimeMillis();
- log.info("调用HCS接口 获取令牌开始");
- HcsResult
- * TODO 待联调确认:v4 未给出 getToken 响应字段示例,expires_in 字段名与单位以实际返回为准(设计文档 §3.2)
- *
- * @param tokenVO 令牌信息
- */
- private void cacheToken(HcsTokenVO tokenVO) {
- if (tokenVO.getExpiresIn() == null || tokenVO.getExpiresIn() <= HcsConstant.TOKEN_EXPIRE_BUFFER_MILLIS) {
- log.warn("HCS令牌未返回有效期或有效期不足缓冲时长,本次不缓存");
- return;
- }
- // 过期时间 - 缓冲时长,防止刚好过期
- long expireMillis = tokenVO.getExpiresIn() - HcsConstant.TOKEN_EXPIRE_BUFFER_MILLIS;
- bladeRedis.getValueOps().setIfAbsent(HcsConstant.HCS_TOKEN_CACHE_KEY, tokenVO.getAccessToken(), Duration.ofMillis(expireMillis));
- log.info("HCS令牌已缓存,有效期 {}ms(含 {}ms 提前失效缓冲)", expireMillis, HcsConstant.TOKEN_EXPIRE_BUFFER_MILLIS);
- }
-
- /**
- * 令牌缓存是否命中(诊断用)
- *
- * @return true-缓存存在
- */
- public boolean isTokenCached() {
- return StringUtil.isNotBlank(Objects.toString(bladeRedis.get(HcsConstant.HCS_TOKEN_CACHE_KEY), null));
- }
-}
- *
- * 取令牌请求本身不追加 access_token(路径守卫 + 空令牌守卫双重防护)。
+ * 两个头均来自 Nacos + 环境变量注入,未配置时告警并放行(由对端返回 401 暴露问题)。
*
* @author Chill
*/
@@ -54,46 +50,23 @@ public class HcsAuthInterceptor implements RequestInterceptor {
private final HcsProperties properties;
- /**
- * 惰性持有令牌服务,打破 Feign 客户端与令牌服务的构造期循环依赖
- */
- private final ObjectProvider