From 5c5d2be0cb36898dcabe0828d7eb5825dc539ade Mon Sep 17 00:00:00 2001 From: zhaojun <873019219@qq.com> Date: Sat, 26 Jul 2025 21:30:48 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E9=9C=80=E8=A6=81=E5=88=B7?= =?UTF-8?q?=E6=96=B0=E4=BB=A4=E7=89=8C=E7=9A=84=E5=AD=98=E5=82=A8=E6=BA=90?= =?UTF-8?q?=EF=BC=8C=E5=8E=BB=E9=99=A4=E5=AE=9A=E6=97=B6=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=E5=88=B7=E6=96=B0=EF=BC=8C=E6=94=B9=E4=B8=BA=E6=AF=8F=E6=AC=A1?= =?UTF-8?q?=E8=AF=B7=E6=B1=82=E6=97=B6=E6=A3=80=E6=9F=A5=E6=98=AF=E5=90=A6?= =?UTF-8?q?=E8=BF=87=E6=9C=9F=E5=B9=B6=E5=88=B7=E6=96=B0=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../constant/StorageConfigConstant.java | 2 + .../storage/model/bo/RefreshTokenCacheBO.java | 33 +++- .../storage/model/dto/OAuth2TokenDTO.java | 8 +- .../model/dto/RefreshTokenInfoDTO.java | 65 +++++++ .../model/dto/StorageSourceAllParamDTO.java | 3 + .../storage/model/param/DogeCloudParam.java | 9 - .../storage/model/param/GoogleDriveParam.java | 3 + .../model/param/MicrosoftDriveParam.java | 3 + .../AbstractMicrosoftOAuth2Service.java | 3 +- .../service/GoogleDriveOAuth2ServiceImpl.java | 3 +- .../oauth2/service/IOAuth2Service.java | 5 + .../schedule/AccessTokenRefreshSchedule.java | 52 ----- .../service/base/AbstractBaseFileService.java | 2 +- .../base/AbstractMicrosoftDriveService.java | 178 +++++++++--------- .../base/AbstractOneDriveServiceBase.java | 5 - .../base/AbstractSharePointServiceBase.java | 5 - .../service/impl/DogeCloudServiceImpl.java | 119 ++++++++---- .../service/impl/GoogleDriveServiceImpl.java | 100 ++++++---- ...ce_config_add_refresh_token_expired_at.sql | 8 + ...ce_config_add_refresh_token_expired_at.sql | 8 + 20 files changed, 376 insertions(+), 238 deletions(-) create mode 100644 src/main/java/im/zhaojun/zfile/module/storage/model/dto/RefreshTokenInfoDTO.java delete mode 100644 src/main/java/im/zhaojun/zfile/module/storage/schedule/AccessTokenRefreshSchedule.java create mode 100644 src/main/resources/db/migration-mysql/V51__storage_source_config_add_refresh_token_expired_at.sql create mode 100644 src/main/resources/db/migration-sqlite/V51__storage_source_config_add_refresh_token_expired_at.sql diff --git a/src/main/java/im/zhaojun/zfile/module/storage/constant/StorageConfigConstant.java b/src/main/java/im/zhaojun/zfile/module/storage/constant/StorageConfigConstant.java index d42f4f4..048eeda 100644 --- a/src/main/java/im/zhaojun/zfile/module/storage/constant/StorageConfigConstant.java +++ b/src/main/java/im/zhaojun/zfile/module/storage/constant/StorageConfigConstant.java @@ -11,6 +11,8 @@ public class StorageConfigConstant { public static final String REFRESH_TOKEN_KEY = "refreshToken"; + public static final String REFRESH_TOKEN_EXPIRED_AT_KEY = "refreshTokenExpiredAt"; + public static final String PROXY_DOWNLOAD_KEY = "enableProxyDownload"; public static final String PROXY_UPLOAD_KEY = "enableProxyUpload"; diff --git a/src/main/java/im/zhaojun/zfile/module/storage/model/bo/RefreshTokenCacheBO.java b/src/main/java/im/zhaojun/zfile/module/storage/model/bo/RefreshTokenCacheBO.java index 81716d6..d91e13e 100644 --- a/src/main/java/im/zhaojun/zfile/module/storage/model/bo/RefreshTokenCacheBO.java +++ b/src/main/java/im/zhaojun/zfile/module/storage/model/bo/RefreshTokenCacheBO.java @@ -2,6 +2,7 @@ package im.zhaojun.zfile.module.storage.model.bo; import cn.hutool.cache.Cache; import cn.hutool.cache.CacheUtil; +import im.zhaojun.zfile.module.storage.model.dto.RefreshTokenInfoDTO; import lombok.Data; import lombok.ToString; @@ -15,10 +16,11 @@ import java.util.Date; @ToString public class RefreshTokenCacheBO { - private static final Cache REFRESH_TOKEN_INFO_CACHE = CacheUtil.newFIFOCache(100); + private static final Cache REFRESH_TOKEN_INFO_CACHE = CacheUtil.newFIFOCache(1024); - public static void putRefreshTokenInfo(Integer storageId, RefreshTokenInfo lastRefreshTime) { - REFRESH_TOKEN_INFO_CACHE.put(storageId, lastRefreshTime); + public static void putRefreshTokenInfo(Integer storageId, RefreshTokenInfo refreshTokenInfo) { + refreshTokenInfo.setStorageId(storageId); + REFRESH_TOKEN_INFO_CACHE.put(storageId, refreshTokenInfo); } public static RefreshTokenInfo getRefreshTokenInfo(Integer storageId) { @@ -28,17 +30,21 @@ public class RefreshTokenCacheBO { @Data public static class RefreshTokenInfo { + private Integer storageId; + private boolean success; private Date lastRefreshTime; private String msg; + private RefreshTokenInfoDTO data; - public static RefreshTokenInfo success() { + public static RefreshTokenInfo success(RefreshTokenInfoDTO data) { RefreshTokenInfo info = new RefreshTokenInfo(); info.setSuccess(true); info.setLastRefreshTime(new Date()); + info.setData(data); return info; } @@ -50,6 +56,25 @@ public class RefreshTokenCacheBO { return info; } + public boolean isExpired() { + if (!success) { + return true; + } + + if (lastRefreshTime == null) { + return true; + } + + if (data == null || data.getExpiredAt() == null) { + return true; + } + + long expireTime = data.getExpiredAt() * 1000L; + long currentTime = System.currentTimeMillis(); + long timeDiff = expireTime - currentTime; + return timeDiff < 5 * 60 * 1000L; + } + } } \ No newline at end of file diff --git a/src/main/java/im/zhaojun/zfile/module/storage/model/dto/OAuth2TokenDTO.java b/src/main/java/im/zhaojun/zfile/module/storage/model/dto/OAuth2TokenDTO.java index 51f56ad..761ba94 100644 --- a/src/main/java/im/zhaojun/zfile/module/storage/model/dto/OAuth2TokenDTO.java +++ b/src/main/java/im/zhaojun/zfile/module/storage/model/dto/OAuth2TokenDTO.java @@ -25,8 +25,13 @@ public class OAuth2TokenDTO { private boolean success; private String body; + + /** + * 令牌到期时间,时间戳,单位毫秒 + */ + private Integer expiredAt; - public static OAuth2TokenDTO success(String clientId, String clientSecret, String redirectUri, String accessToken, String refreshToken, String body) { + public static OAuth2TokenDTO success(String clientId, String clientSecret, String redirectUri, String accessToken, String refreshToken, String body, Integer expiredAt) { OAuth2TokenDTO token = new OAuth2TokenDTO(); token.setClientId(clientId); token.setClientSecret(clientSecret); @@ -35,6 +40,7 @@ public class OAuth2TokenDTO { token.setBody(body); token.setAccessToken(accessToken); token.setRefreshToken(refreshToken); + token.setExpiredAt(expiredAt); return token; } diff --git a/src/main/java/im/zhaojun/zfile/module/storage/model/dto/RefreshTokenInfoDTO.java b/src/main/java/im/zhaojun/zfile/module/storage/model/dto/RefreshTokenInfoDTO.java new file mode 100644 index 0000000..2dc62a4 --- /dev/null +++ b/src/main/java/im/zhaojun/zfile/module/storage/model/dto/RefreshTokenInfoDTO.java @@ -0,0 +1,65 @@ +package im.zhaojun.zfile.module.storage.model.dto; + +import lombok.Data; + +import java.util.Date; + +@Data +public class RefreshTokenInfoDTO { + + /** + * 访问令牌,用于访问受保护的资源 + */ + private String accessToken; + + /** + * 刷新令牌,用于获取新的访问令牌 + */ + private String refreshToken; + + /** + * 会话令牌,通常用于 AWS 等云存储服务的临时凭证 + */ + private String sessionToken; + + /** + * 过期时间戳(单位: 秒) + */ + private Integer expiredAt; + + public Date getExpiredAtDate() { + if (expiredAt == null) { + return null; + } + // 如果 expiredAt 是 10 位时间戳(秒) + if (expiredAt > 1_000_000_000) { + return new Date(expiredAt * 1000L); + } else { + // 否则认为 expiredAt 是过期时间(单位: 秒) + return new Date((expiredAt + System.currentTimeMillis() / 1000) * 1000L); + } + } + + public static RefreshTokenInfoDTO success(String accessToken, String refreshToken, String sessionToken, Integer expiredAt) { + RefreshTokenInfoDTO token = new RefreshTokenInfoDTO(); + token.setAccessToken(accessToken); + token.setRefreshToken(refreshToken); + token.setSessionToken(sessionToken); + + if (expiredAt != null) { + // 如果 expiredAt 是 10 位时间戳(秒) + if (expiredAt > 1_000_000_000) { + token.setExpiredAt(expiredAt); + } else { + // 否则认为 expiredAt 是过期时间(单位: 秒) + token.setExpiredAt(expiredAt + (int) (System.currentTimeMillis() / 1000)); + } + } + return token; + } + + public static RefreshTokenInfoDTO success(String accessToken, String refreshToken, Integer expiredAt) { + return success(accessToken, refreshToken, null, expiredAt); + } + +} diff --git a/src/main/java/im/zhaojun/zfile/module/storage/model/dto/StorageSourceAllParamDTO.java b/src/main/java/im/zhaojun/zfile/module/storage/model/dto/StorageSourceAllParamDTO.java index 06268f9..aded028 100644 --- a/src/main/java/im/zhaojun/zfile/module/storage/model/dto/StorageSourceAllParamDTO.java +++ b/src/main/java/im/zhaojun/zfile/module/storage/model/dto/StorageSourceAllParamDTO.java @@ -59,6 +59,9 @@ public class StorageSourceAllParamDTO implements Serializable { @Schema(name = "刷新令牌", example = "15063f61.86400.1292922000-2346678-1243281asd-1asa") private String refreshToken; + @Schema(name = "刷新令牌到期时间(秒)", example = "1752994685") + private Integer refreshTokenExpiredAt; + @Schema(name = "secretId", example = "LTAI4FjfXqXxQZQZ") private String secretId; diff --git a/src/main/java/im/zhaojun/zfile/module/storage/model/param/DogeCloudParam.java b/src/main/java/im/zhaojun/zfile/module/storage/model/param/DogeCloudParam.java index aa77178..e149298 100644 --- a/src/main/java/im/zhaojun/zfile/module/storage/model/param/DogeCloudParam.java +++ b/src/main/java/im/zhaojun/zfile/module/storage/model/param/DogeCloudParam.java @@ -21,15 +21,6 @@ public class DogeCloudParam extends S3BaseParam { @StorageParamItem(ignoreInput = true, onlyOverwrite = { StorageParamItemAnnoEnum.IGNORE_INPUT }) private String bucketName; - @StorageParamItem(ignoreInput = true, onlyOverwrite = { StorageParamItemAnnoEnum.IGNORE_INPUT }) - private String s3AccessKey; - - @StorageParamItem(ignoreInput = true, onlyOverwrite = { StorageParamItemAnnoEnum.IGNORE_INPUT }) - private String s3SecretKey; - - @StorageParamItem(ignoreInput = true, onlyOverwrite = { StorageParamItemAnnoEnum.IGNORE_INPUT }) - private String s3SessionToken; - @StorageParamItem(name = "存储空间名称", order = 40) private String originBucketName; diff --git a/src/main/java/im/zhaojun/zfile/module/storage/model/param/GoogleDriveParam.java b/src/main/java/im/zhaojun/zfile/module/storage/model/param/GoogleDriveParam.java index adf1dcb..493cd96 100644 --- a/src/main/java/im/zhaojun/zfile/module/storage/model/param/GoogleDriveParam.java +++ b/src/main/java/im/zhaojun/zfile/module/storage/model/param/GoogleDriveParam.java @@ -31,6 +31,9 @@ public class GoogleDriveParam extends ProxyTransferParam { @StorageParamItem(name = "刷新令牌", order = 5) private String refreshToken; + @StorageParamItem(name = "刷新令牌到期时间戳(秒)", hidden = true, required = false) + private Integer refreshTokenExpiredAt; + @StorageParamItem(name = "网盘", order = 6, required = false) private String driveId; diff --git a/src/main/java/im/zhaojun/zfile/module/storage/model/param/MicrosoftDriveParam.java b/src/main/java/im/zhaojun/zfile/module/storage/model/param/MicrosoftDriveParam.java index df6c82d..ec1fb1f 100644 --- a/src/main/java/im/zhaojun/zfile/module/storage/model/param/MicrosoftDriveParam.java +++ b/src/main/java/im/zhaojun/zfile/module/storage/model/param/MicrosoftDriveParam.java @@ -27,6 +27,9 @@ public class MicrosoftDriveParam extends OptionalProxyTransferParam { @StorageParamItem(name = "刷新令牌", order = 5) private String refreshToken; + @StorageParamItem(name = "刷新令牌到期时间戳(秒)", hidden = true, required = false) + private Integer refreshTokenExpiredAt; + @StorageParamItem(name = "基路径", defaultValue = "/", order = 6, description = "基路径表示该存储源哪个目录在 ZFile 中作为根目录,如: '/','/文件夹1'") private String basePath; diff --git a/src/main/java/im/zhaojun/zfile/module/storage/oauth2/service/AbstractMicrosoftOAuth2Service.java b/src/main/java/im/zhaojun/zfile/module/storage/oauth2/service/AbstractMicrosoftOAuth2Service.java index 552b3a2..0618917 100644 --- a/src/main/java/im/zhaojun/zfile/module/storage/oauth2/service/AbstractMicrosoftOAuth2Service.java +++ b/src/main/java/im/zhaojun/zfile/module/storage/oauth2/service/AbstractMicrosoftOAuth2Service.java @@ -66,7 +66,8 @@ public abstract class AbstractMicrosoftOAuth2Service implements IOAuth2Service { JSONObject jsonBody = JSONObject.parseObject(responseBody); String accessToken = jsonBody.getString(ACCESS_TOKEN_FIELD_NAME); String refreshToken = jsonBody.getString(REFRESH_TOKEN_FIELD_NAME); - return OAuth2TokenDTO.success(clientId, clientSecret, redirectUri, accessToken, refreshToken, responseBody); + Integer expiresIn = jsonBody.getInteger(EXPIRES_IN_FIELD_NAME); + return OAuth2TokenDTO.success(clientId, clientSecret, redirectUri, accessToken, refreshToken, responseBody, expiresIn); } public abstract String getEndPoint(); diff --git a/src/main/java/im/zhaojun/zfile/module/storage/oauth2/service/GoogleDriveOAuth2ServiceImpl.java b/src/main/java/im/zhaojun/zfile/module/storage/oauth2/service/GoogleDriveOAuth2ServiceImpl.java index e060eb4..bcf4ad6 100644 --- a/src/main/java/im/zhaojun/zfile/module/storage/oauth2/service/GoogleDriveOAuth2ServiceImpl.java +++ b/src/main/java/im/zhaojun/zfile/module/storage/oauth2/service/GoogleDriveOAuth2ServiceImpl.java @@ -77,7 +77,8 @@ public class GoogleDriveOAuth2ServiceImpl implements IOAuth2Service { String accessToken = jsonBody.getString(ACCESS_TOKEN_FIELD_NAME); String refreshToken = jsonBody.getString(REFRESH_TOKEN_FIELD_NAME); - return OAuth2TokenDTO.success(clientId, clientSecret, redirectUri, accessToken, refreshToken, responseBody); + Integer expiresIn = jsonBody.getInteger(EXPIRES_IN_FIELD_NAME); + return OAuth2TokenDTO.success(clientId, clientSecret, redirectUri, accessToken, refreshToken, responseBody, expiresIn); } diff --git a/src/main/java/im/zhaojun/zfile/module/storage/oauth2/service/IOAuth2Service.java b/src/main/java/im/zhaojun/zfile/module/storage/oauth2/service/IOAuth2Service.java index e954007..b856385 100644 --- a/src/main/java/im/zhaojun/zfile/module/storage/oauth2/service/IOAuth2Service.java +++ b/src/main/java/im/zhaojun/zfile/module/storage/oauth2/service/IOAuth2Service.java @@ -14,6 +14,11 @@ public interface IOAuth2Service { */ String REFRESH_TOKEN_FIELD_NAME = "refresh_token"; + /** + * 过期时间字段名称 + */ + String EXPIRES_IN_FIELD_NAME = "expires_in"; + String generateAuthorizationUrl(String clientId, String clientSecret, String redirectUri); diff --git a/src/main/java/im/zhaojun/zfile/module/storage/schedule/AccessTokenRefreshSchedule.java b/src/main/java/im/zhaojun/zfile/module/storage/schedule/AccessTokenRefreshSchedule.java deleted file mode 100644 index e6294a4..0000000 --- a/src/main/java/im/zhaojun/zfile/module/storage/schedule/AccessTokenRefreshSchedule.java +++ /dev/null @@ -1,52 +0,0 @@ -package im.zhaojun.zfile.module.storage.schedule; - -import im.zhaojun.zfile.module.storage.context.StorageSourceContext; -import im.zhaojun.zfile.module.storage.service.base.RefreshTokenService; -import lombok.extern.slf4j.Slf4j; -import org.springframework.context.annotation.Configuration; -import org.springframework.scheduling.annotation.EnableScheduling; -import org.springframework.scheduling.annotation.Scheduled; - -import jakarta.annotation.Resource; -import java.util.Map; - -/** - * 刷新使用所有 AccessToken 机制的定时任务, 存储源实现 #{@link RefreshTokenService} 接口, 表示是需要刷新 AccessToken 的存储源 - * - * @author zhaojun - */ -@Configuration -@EnableScheduling -@Slf4j -public class AccessTokenRefreshSchedule { - - /** - * 项目启动 30 秒后, 每 10 分钟执行一次刷新 OneDrive Token 的定时任务. - */ - @Scheduled(fixedRate = 1000 * 60 * 10, initialDelay = 1000 * 10) - public void autoRefreshAccessToken() { - if (log.isDebugEnabled()) { - log.debug("开始执行需要定期刷新 AccessToken 存储源的定时任务"); - } - - Map refreshTokenServiceMap = StorageSourceContext.getAllRefreshTokenStorageSource(); - - for (Map.Entry refreshTokenServiceEntry : refreshTokenServiceMap.entrySet()) { - Integer storageId = refreshTokenServiceEntry.getKey(); - RefreshTokenService refreshTokenService = refreshTokenServiceEntry.getValue(); - try { - refreshTokenService.refreshAccessToken(); - log.info("成功刷新存储源 AccessToken, 存储源 id: {}, 存储源类型: {}", - storageId, refreshTokenService.getStorageTypeEnum().getDescription()); - } catch (Exception e) { - log.error("刷新存储源 AccessToken 失败, 存储源 id: {}, 存储源类型: {}", - storageId, refreshTokenService.getStorageTypeEnum().getDescription(), e); - } - } - - if (log.isDebugEnabled()) { - log.debug("执行需要定期刷新 AccessToken 存储源的定时任务完成"); - } - } - -} \ No newline at end of file diff --git a/src/main/java/im/zhaojun/zfile/module/storage/service/base/AbstractBaseFileService.java b/src/main/java/im/zhaojun/zfile/module/storage/service/base/AbstractBaseFileService.java index 6e3293a..4e4df90 100644 --- a/src/main/java/im/zhaojun/zfile/module/storage/service/base/AbstractBaseFileService.java +++ b/src/main/java/im/zhaojun/zfile/module/storage/service/base/AbstractBaseFileService.java @@ -78,7 +78,7 @@ public abstract class AbstractBaseFileService

implement } } - String getStorageSimpleInfo() { + protected String getStorageSimpleInfo() { return String.format("存储源 [id=%s, name=%s, type: %s]", storageId, name, getStorageTypeEnum().getDescription()); } diff --git a/src/main/java/im/zhaojun/zfile/module/storage/service/base/AbstractMicrosoftDriveService.java b/src/main/java/im/zhaojun/zfile/module/storage/service/base/AbstractMicrosoftDriveService.java index eed045d..4f706bc 100644 --- a/src/main/java/im/zhaojun/zfile/module/storage/service/base/AbstractMicrosoftDriveService.java +++ b/src/main/java/im/zhaojun/zfile/module/storage/service/base/AbstractMicrosoftDriveService.java @@ -1,9 +1,13 @@ package im.zhaojun.zfile.module.storage.service.base; +import cn.hutool.core.convert.Convert; import cn.hutool.core.util.URLUtil; import cn.hutool.http.ContentType; import cn.hutool.http.HttpResponse; import cn.hutool.http.HttpUtil; +import cn.hutool.jwt.JWT; +import cn.hutool.jwt.JWTPayload; +import cn.hutool.jwt.JWTUtil; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import im.zhaojun.zfile.core.exception.ErrorCode; @@ -17,12 +21,14 @@ import im.zhaojun.zfile.core.util.StringUtils; import im.zhaojun.zfile.module.storage.constant.StorageConfigConstant; import im.zhaojun.zfile.module.storage.model.bo.RefreshTokenCacheBO; import im.zhaojun.zfile.module.storage.model.bo.StorageSourceMetadata; -import im.zhaojun.zfile.module.storage.model.dto.OAuth2TokenDTO; +import im.zhaojun.zfile.module.storage.model.dto.RefreshTokenInfoDTO; import im.zhaojun.zfile.module.storage.model.entity.StorageSourceConfig; import im.zhaojun.zfile.module.storage.model.enums.FileTypeEnum; import im.zhaojun.zfile.module.storage.model.param.MicrosoftDriveParam; import im.zhaojun.zfile.module.storage.model.result.FileItemResult; +import im.zhaojun.zfile.module.storage.oauth2.service.IOAuth2Service; import im.zhaojun.zfile.module.storage.service.StorageSourceConfigService; +import jakarta.annotation.Nullable; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.apache.hc.client5.http.classic.HttpClient; @@ -30,13 +36,9 @@ import org.apache.hc.client5.http.config.RequestConfig; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; import org.apache.hc.core5.util.Timeout; -import org.jetbrains.annotations.Nullable; import org.springframework.http.*; -import org.springframework.http.client.*; -import org.springframework.retry.RetryCallback; -import org.springframework.retry.support.RetryTemplate; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.util.StreamUtils; -import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.ResourceAccessException; import org.springframework.web.client.RestTemplate; @@ -92,22 +94,36 @@ public abstract class AbstractMicrosoftDriveService

{ - int retryCount = context.getRetryCount(); - if (retryCount > 0) { - HttpClientErrorException ex = (HttpClientErrorException) context.getLastThrowable(); - log.warn("{} 调用 OneDrive 列表时出现了网络异常, 响应信息: [{}], 将尝试重新刷新 token 后再试. 文件路径为: [{}]", - getStorageSimpleInfo(), ex.getResponseBodyAsString(), fullPath, ex); - refreshAccessToken(); - } - - HttpEntity entity = getAuthorizationHttpEntity(); - return getRestTemplate().exchange(requestUrl, HttpMethod.GET, entity, JSONObject.class, getGraphEndPoint(), getType(), fullPath).getBody(); - }); - + HttpEntity entity = getAuthorizationHttpEntity(); + JSONObject root = getRestTemplate().exchange(requestUrl, HttpMethod.GET, entity, JSONObject.class, getGraphEndPoint(), getType(), fullPath).getBody(); if (root == null) { return Collections.emptyList(); } @@ -201,25 +206,8 @@ public abstract class AbstractMicrosoftDriveService

{ - int retryCount = context.getRetryCount(); - if (retryCount > 0) { - refreshAccessToken(); - HttpClientErrorException ex = (HttpClientErrorException) context.getLastThrowable(); - // 404 代表文件不存在, 直接返回 null - if (ex instanceof HttpClientErrorException.NotFound) { - return null; - } - log.warn("{} 调用 OneDrive 获取文件信息时出现了网络异常, 响应信息: [{}], 将尝试重新刷新 token 后再试. 获取文件路径为: {}", - getStorageSimpleInfo(), ex.getResponseBodyAsString(), fullPath, ex); - - } - - HttpEntity entity = getAuthorizationHttpEntity(); - return getRestTemplate().exchange(DRIVER_ITEM_URL, HttpMethod.GET, entity, JSONObject.class, getGraphEndPoint(), getType(), fullPath).getBody(); - }); + HttpEntity entity = getAuthorizationHttpEntity(); + return getRestTemplate().exchange(DRIVER_ITEM_URL, HttpMethod.GET, entity, JSONObject.class, getGraphEndPoint(), getType(), fullPath).getBody(); } @@ -470,23 +458,23 @@ public abstract class AbstractMicrosoftDriveService

HttpEntity getAuthorizationHttpEntity(T body) { HttpHeaders headers = new HttpHeaders(); - StorageSourceConfig accessTokenConfig = - storageSourceConfigService.findByStorageIdAndName(storageId, StorageConfigConstant.ACCESS_TOKEN_KEY); - headers.setBearerAuth(accessTokenConfig.getValue()); + String accessToken = checkExpiredAndGetAccessToken(); + headers.setBearerAuth(accessToken); return new HttpEntity<>(body, headers); } - - - /** - * 执行可重试 1 次的任务, 对抛出的异常转为 ZFileRetryException(Unchecked Exception) - * @param retryCallback 可重试的任务 - * @return 任务执行结果 - * - * @param 任务执行结果类型 - */ - private T executeRetryableRequest(RetryCallback retryCallback) { - RetryTemplate retryTemplate = RetryTemplate.builder().maxAttempts(2).retryOn(HttpClientErrorException.class).build(); - - T result; - try { - result = retryTemplate.execute(retryCallback); - } catch (Throwable e) { - throw new SystemException("请求失败", e); - } - - return result; - } @Override public StorageSourceMetadata getStorageSourceMetadata() { @@ -590,7 +556,7 @@ public abstract class AbstractMicrosoftDriveService

extends AbstractMicrosoftDriveService

{ - @Override - public void init() { - refreshAccessToken(); - } - @Override public String getType() { return "me"; diff --git a/src/main/java/im/zhaojun/zfile/module/storage/service/base/AbstractSharePointServiceBase.java b/src/main/java/im/zhaojun/zfile/module/storage/service/base/AbstractSharePointServiceBase.java index b98ed6c..d267b51 100644 --- a/src/main/java/im/zhaojun/zfile/module/storage/service/base/AbstractSharePointServiceBase.java +++ b/src/main/java/im/zhaojun/zfile/module/storage/service/base/AbstractSharePointServiceBase.java @@ -7,11 +7,6 @@ import im.zhaojun.zfile.module.storage.model.param.SharePointParam; */ public abstract class AbstractSharePointServiceBase

extends AbstractMicrosoftDriveService { - @Override - public void init() { - refreshAccessToken(); - } - @Override public String getType() { return "sites/" + param.getSiteId(); diff --git a/src/main/java/im/zhaojun/zfile/module/storage/service/impl/DogeCloudServiceImpl.java b/src/main/java/im/zhaojun/zfile/module/storage/service/impl/DogeCloudServiceImpl.java index eb1a9a4..3ceb453 100644 --- a/src/main/java/im/zhaojun/zfile/module/storage/service/impl/DogeCloudServiceImpl.java +++ b/src/main/java/im/zhaojun/zfile/module/storage/service/impl/DogeCloudServiceImpl.java @@ -8,6 +8,8 @@ import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import im.zhaojun.zfile.core.exception.core.BizException; import im.zhaojun.zfile.core.exception.core.SystemException; +import im.zhaojun.zfile.module.storage.model.bo.RefreshTokenCacheBO; +import im.zhaojun.zfile.module.storage.model.dto.RefreshTokenInfoDTO; import im.zhaojun.zfile.module.storage.model.enums.StorageTypeEnum; import im.zhaojun.zfile.module.storage.model.param.DogeCloudParam; import im.zhaojun.zfile.module.storage.service.base.AbstractS3BaseFileService; @@ -16,6 +18,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; +import software.amazon.awssdk.auth.credentials.AwsCredentials; import software.amazon.awssdk.auth.credentials.AwsSessionCredentials; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.s3.S3Client; @@ -31,10 +34,11 @@ import java.net.URI; @Slf4j public class DogeCloudServiceImpl extends AbstractS3BaseFileService implements RefreshTokenService { + private AwsCredentials awsCredentials; + @Override public void init() { refreshAccessToken(); - Region oss = Region.of("automatic"); URI endpointOverride = URI.create(param.getEndPoint()); @@ -42,16 +46,14 @@ public class DogeCloudServiceImpl extends AbstractS3BaseFileService AwsSessionCredentials.create(param.getS3AccessKey(), param.getS3SecretKey(), param.getS3SessionToken())) + .credentialsProvider(this::checkExpiredAndGetAwsCredentials) .build(); super.s3Presigner = S3Presigner.builder() .region(oss) .endpointOverride(endpointOverride) - .credentialsProvider(() -> AwsSessionCredentials.create(param.getS3AccessKey(), param.getS3SecretKey(), param.getS3SessionToken())) + .credentialsProvider(this::checkExpiredAndGetAwsCredentials) .build(); - - } @Override @@ -61,48 +63,93 @@ public class DogeCloudServiceImpl extends AbstractS3BaseFileService