From e15394fa4daef52431022dfeb555e651be1c75f7 Mon Sep 17 00:00:00 2001 From: zhangli <123879394@qq.com> Date: Mon, 11 Aug 2025 22:42:12 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=9F=A5=E8=AF=A2OSS?= =?UTF-8?q?=E7=9A=84plicy=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Jenkinsfile | 1 + pom.xml | 6 ++ .../java/com/sczx/store/config/OSSConfig.java | 14 ++++ .../sczx/store/controller/OssController.java | 26 +++++++ .../java/com/sczx/store/dto/OssPlicyReq.java | 19 +++++ .../java/com/sczx/store/dto/OssPolicyRes.java | 22 ++++++ .../com/sczx/store/service/OssService.java | 8 ++ .../store/service/impl/OssServiceImpl.java | 75 +++++++++++++++++++ src/main/resources/application-local.yml | 1 + src/main/resources/application-test.yml | 1 + src/main/resources/application.yml | 5 ++ 11 files changed, 178 insertions(+) create mode 100644 src/main/java/com/sczx/store/config/OSSConfig.java create mode 100644 src/main/java/com/sczx/store/controller/OssController.java create mode 100644 src/main/java/com/sczx/store/dto/OssPlicyReq.java create mode 100644 src/main/java/com/sczx/store/dto/OssPolicyRes.java create mode 100644 src/main/java/com/sczx/store/service/OssService.java create mode 100644 src/main/java/com/sczx/store/service/impl/OssServiceImpl.java create mode 100644 src/main/resources/application-local.yml create mode 100644 src/main/resources/application-test.yml diff --git a/Jenkinsfile b/Jenkinsfile index a30190b..5b8dfb0 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -59,6 +59,7 @@ pipeline { --name \${CONTAINER_NAME} \ --network sczx-net \ -p 8082:8082 \ + -e SPRING_PROFILES_ACTIVE=test \ -e JAVA_OPTS="-Xms256m -Xmx512m -Duser.timezone=Asia/Shanghai" \ --restart always \ \${DOCKER_IMAGE} diff --git a/pom.xml b/pom.xml index a4da891..e7ae583 100644 --- a/pom.xml +++ b/pom.xml @@ -222,6 +222,12 @@ fastjson 1.2.83 + + + commons-codec + commons-codec + 1.15 + diff --git a/src/main/java/com/sczx/store/config/OSSConfig.java b/src/main/java/com/sczx/store/config/OSSConfig.java new file mode 100644 index 0000000..3fc6430 --- /dev/null +++ b/src/main/java/com/sczx/store/config/OSSConfig.java @@ -0,0 +1,14 @@ +package com.sczx.store.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +@Data +@Component +@ConfigurationProperties(prefix = "oss") +public class OSSConfig { + private String region; + private String accessKeyId; + private String accessKeySecret; +} diff --git a/src/main/java/com/sczx/store/controller/OssController.java b/src/main/java/com/sczx/store/controller/OssController.java new file mode 100644 index 0000000..6e2970c --- /dev/null +++ b/src/main/java/com/sczx/store/controller/OssController.java @@ -0,0 +1,26 @@ +package com.sczx.store.controller; + +import com.sczx.store.common.Result; +import com.sczx.store.dto.OssPlicyReq; +import com.sczx.store.dto.OssPolicyRes; +import com.sczx.store.service.OssService; +import io.swagger.annotations.Api; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Api(value = "oss接口", tags = "oss接口") +@RestController +@RequestMapping("/oss") +public class OssController { + + @Autowired + private OssService ossService; + + @PostMapping("/policy") + public Result policy(@RequestBody OssPlicyReq ossPlicyReq) { + return Result.ok(ossService.getPolicy(ossPlicyReq)); + } +} diff --git a/src/main/java/com/sczx/store/dto/OssPlicyReq.java b/src/main/java/com/sczx/store/dto/OssPlicyReq.java new file mode 100644 index 0000000..e6e169c --- /dev/null +++ b/src/main/java/com/sczx/store/dto/OssPlicyReq.java @@ -0,0 +1,19 @@ +package com.sczx.store.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@ApiModel(value = "OssPlicy请求对象", description = "OssPlicyReq对象") +@Data +public class OssPlicyReq { + + @ApiModelProperty(value = "过期时间") + private long expireTime; + + @ApiModelProperty(value = "上传目录") + private String dir; + + @ApiModelProperty(value = "bucket名称") + private String bucketName; +} diff --git a/src/main/java/com/sczx/store/dto/OssPolicyRes.java b/src/main/java/com/sczx/store/dto/OssPolicyRes.java new file mode 100644 index 0000000..dd10958 --- /dev/null +++ b/src/main/java/com/sczx/store/dto/OssPolicyRes.java @@ -0,0 +1,22 @@ +package com.sczx.store.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +@ApiModel(value = "OSS上传策略返回对象", description = "OSS上传策略") +public class OssPolicyRes { + @ApiModelProperty(value = "accessKeyId", required = true) + private String accessid; + @ApiModelProperty(value = "上传策略,需要后端生成", required = true) + private String policy; + @ApiModelProperty(value = "signature:签名,基于 accessKeySecret 生成", required = true) + private String signature; + @ApiModelProperty(value = "dir:上传目录(可选)", required = false) + private String dir; + @ApiModelProperty(value = "host:OSS 访问域名", required = true) + private String host; + @ApiModelProperty(value = "expire:过期时间", required = true) + private Long expire; +} diff --git a/src/main/java/com/sczx/store/service/OssService.java b/src/main/java/com/sczx/store/service/OssService.java new file mode 100644 index 0000000..adc4597 --- /dev/null +++ b/src/main/java/com/sczx/store/service/OssService.java @@ -0,0 +1,8 @@ +package com.sczx.store.service; + +import com.sczx.store.dto.OssPlicyReq; +import com.sczx.store.dto.OssPolicyRes; + +public interface OssService { + OssPolicyRes getPolicy(OssPlicyReq ossPlicyReq); +} diff --git a/src/main/java/com/sczx/store/service/impl/OssServiceImpl.java b/src/main/java/com/sczx/store/service/impl/OssServiceImpl.java new file mode 100644 index 0000000..94daf5c --- /dev/null +++ b/src/main/java/com/sczx/store/service/impl/OssServiceImpl.java @@ -0,0 +1,75 @@ +package com.sczx.store.service.impl; + +import com.sczx.store.config.OSSConfig; +import com.sczx.store.dto.OssPlicyReq; +import com.sczx.store.dto.OssPolicyRes; +import com.sczx.store.service.OssService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import java.nio.charset.StandardCharsets; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Base64; +import java.util.Date; +import java.util.LinkedHashMap; +import java.util.Map; + +@Slf4j +@Service +public class OssServiceImpl implements OssService { + + @Autowired + private OSSConfig ossConfig; + + @Override + public OssPolicyRes getPolicy(OssPlicyReq ossPlicyReq) { + + long expireEndTime = System.currentTimeMillis() + ossPlicyReq.getExpireTime() * 1000; + Date expiration = new Date(expireEndTime); + DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); + String expire = df.format(expiration); + + // 创建policy + Map policyMap = new LinkedHashMap<>(); + policyMap.put("expiration", expire); + + Map conditionMap = new LinkedHashMap<>(); + conditionMap.put("bucket", ossPlicyReq.getBucketName()); // 需要替换成你的 bucket 名称 + + policyMap.put("conditions", new Object[]{conditionMap}); + + String policy = Base64.getEncoder().encodeToString(policyMap.toString().getBytes(StandardCharsets.UTF_8)); + String signature = calculateSignature(ossConfig.getAccessKeySecret(), policy); + + // 构造返回数据 + OssPolicyRes response = new OssPolicyRes(); + response.setAccessid(ossConfig.getAccessKeyId()); + response.setPolicy(policy); + response.setSignature(signature); + response.setDir(ossPlicyReq.getDir()+"/"); // 可以自定义上传目录 + response.setHost("https://" + ossPlicyReq.getBucketName() + "." + ossConfig.getRegion() + ".aliyuncs.com"); // 需要替换成你的 bucket 名称 + response.setExpire(expireEndTime / 1000); + return response; + } + + /** + * 计算签名 + * @param accessKeySecret + * @param policy + * @return + */ + private String calculateSignature(String accessKeySecret, String policy) { + try { + Mac mac = Mac.getInstance("HmacSHA1"); + mac.init(new SecretKeySpec(accessKeySecret.getBytes(StandardCharsets.UTF_8), "HmacSHA1")); + byte[] signData = mac.doFinal(policy.getBytes(StandardCharsets.UTF_8)); + return Base64.getEncoder().encodeToString(signData); + } catch (Exception e) { + throw new RuntimeException("计算签名失败", e); + } + } +} diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/main/resources/application-local.yml @@ -0,0 +1 @@ + diff --git a/src/main/resources/application-test.yml b/src/main/resources/application-test.yml new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/main/resources/application-test.yml @@ -0,0 +1 @@ + diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index e2d1b7a..5a8ca86 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -84,3 +84,8 @@ mybatis-plus: auth: secret-key: his-is-a-very-long-and-secure-secret-key-for-jwt-signing-please-dont-use-short-keys token-expiration: 86400000 # 24小时 + +oss: + region: oss-cn-shanghai + accessKeyId: LTAI5tFZygsWsFqAqUbBmCrB + accessKeySecret: n417ym6PZyq5Gc4NHHps3EwzNiClDJ \ No newline at end of file