Files
huitu/ruoyi-main/ruoyi-custom/src/main/java/com/ruoyi/controller/ApiOcsController.java
2025-04-08 16:37:17 +08:00

325 lines
15 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.ruoyi.controller;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.cos.auth.COSSigner;
import com.ruoyi.response.ResponseData;
import com.ruoyi.system.service.ISysDictDataService;
import com.tencent.cloud.CosStsClient;
import com.tencent.cloud.Policy;
import com.tencent.cloud.Response;
import com.tencent.cloud.Statement;
import com.tencent.cloud.cos.util.Jackson;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.constraints.NotBlank;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
/**
* @Author OCS
* @Date 2022/2/8 16:40
*/
@CrossOrigin
@RestController
@Slf4j
@RequestMapping("/api/cos")
@Api(tags = "OCS")
public class ApiOcsController {
@Autowired
private ISysDictDataService iSysDictDataService;
// 根据 github 提供的 maven 集成方法导入 java sts sdk使用 3.1.1 及更高版本
public static void main(String[] args) {
TreeMap<String, Object> config = new TreeMap<String, Object>();
try {
//这里的 SecretId 和 SecretKey 代表了用于申请临时密钥的永久身份(主账号、子账号等),子账号需要具有操作存储桶的权限。
String secretKey = "VXZWQPYaedvMC6vovAU3gJ1ogXXdvO1n";
String secretId = "AKIDSBQuX5mAZvHa2jNwSzWE0lNvNuMjA9gC";
String region = "ap-shanghai";
String bucket = "ddht-1324395003";
// 替换为您的云 api 密钥 SecretId
config.put("secretId", secretId);
// 替换为您的云 api 密钥 SecretKey
config.put("secretKey", secretKey);
// 初始化 policy
Policy policy = new Policy();
// 设置域名:
// 如果您使用了腾讯云 cvm可以设置内部域名
//config.put("host", "sts.internal.tencentcloudapi.com");
// 临时密钥有效时长,单位是秒,默认 1800 秒,目前主账号最长 2 小时(即 7200 秒),子账号最长 36 小时(即 129600
config.put("durationSeconds", 1800);
// 换成您的 bucket
config.put("bucket", bucket);
// 换成 bucket 所在地区
config.put("region", region);
// 开始构建一条 statement
Statement statement = new Statement();
// 声明设置的结果是允许操作
statement.setEffect("allow");
/**
* 密钥的权限列表。必须在这里指定本次临时密钥所需要的权限。
* 权限列表请参见 https://cloud.tencent.com/document/product/436/31923
* 规则为 {project}:{interfaceName}
* project : 产品缩写 cos相关授权为值为cos,数据万象(数据处理)相关授权值为ci
* 授权所有接口用*表示,例如 cos:*,ci:*
* 添加一批操作权限 :
*/
statement.addActions(new String[]{
"cos:PutObject",
// 表单上传、小程序上传
"cos:PostObject",
// 分块上传
"cos:InitiateMultipartUpload",
"cos:ListMultipartUploads",
"cos:ListParts",
"cos:UploadPart",
"cos:CompleteMultipartUpload",
// 处理相关接口一般为数据万象产品 权限中以ci开头
// 创建媒体处理任务
"ci:CreateMediaJobs",
// 文件压缩
"ci:CreateFileProcessJobs"
});
/**
* 这里改成允许的路径前缀,可以根据自己网站的用户登录态判断允许上传的具体路径
* 资源表达式规则分对象存储(cos)和数据万象(ci)两种
* 数据处理、审核相关接口需要授予ci资源权限
* cos : qcs::cos:{region}:uid/{appid}:{bucket}/{path}
* ci : qcs::ci:{region}:uid/{appid}:bucket/{bucket}/{path}
* 列举几种典型的{path}授权场景:
* 1、允许访问所有对象"*"
* 2、允许访问指定的对象"a/a1.txt", "b/b1.txt"
* 3、允许访问指定前缀的对象"a*", "a/*", "b/*"
* 如果填写了“*”,将允许用户访问所有资源;除非业务需要,否则请按照最小权限原则授予用户相应的访问权限范围。
*
* 示例授权examplebucket-1250000000 bucket目录下的所有资源给cos和ci 授权两条Resource
*/
statement.addResources(new String[]{
"qcs::cos:" + region + ":uid/" + bucket.split("-")[1] + ":" + bucket + "/*",
"qcs::ci:" + region + ":uid/" + bucket.split("-")[1] + ":bucket/" + bucket + "/*"});
// String secretKey = "VXZWQPYaedvMC6vovAU3gJ1ogXXdvO1n";
// String secretId = "AKIDSBQuX5mAZvHa2jNwSzWE0lNvNuMjA9gC";
//
// String region = "ap-shanghai";
// String bucket = "ddht-1324395003";
statement.addResources(new String[]{
"qcs::cos:ap-shanghai:uid/1324395003:ddht-1324395003/*",
"qcs::ci:ap-shanghai:uid/1324395003:bucket/ddht-1324395003/*"});
// 把一条 statement 添加到 policy
// 可以添加多条
policy.addStatement(statement);
// 将 Policy 示例转化成 String可以使用任何 json 转化方式,这里是本 SDK 自带的推荐方式
config.put("policy", Jackson.toJsonPrettyString(policy));
Response response = CosStsClient.getCredential(config);
System.out.println(response.credentials.tmpSecretId);
System.out.println(response.credentials.tmpSecretKey);
System.out.println(response.credentials.sessionToken);
} catch (Exception e) {
e.printStackTrace();
throw new IllegalArgumentException("no valid secret !");
}
}
// 根据 github 提供的 maven 集成方法导入 java sts sdk使用 3.1.1 及更高版本
@PostMapping("/signNew")
public ResponseData signNew() {
TreeMap<String, Object> config = new TreeMap<String, Object>();
try {
String secretKey = "VXZWQPYaedvMC6vovAU3gJ1ogXXdvO1n";
String secretId = "AKIDSBQuX5mAZvHa2jNwSzWE0lNvNuMjA9gC";
String region = "ap-shanghai";
String bucket = "ddht-1324395003";
SysDictData sysDictData = new SysDictData();
sysDictData.setDictType("storing_param");
List<SysDictData> list = iSysDictDataService.selectDictDataList(sysDictData);
for (SysDictData data : list) {
if ("Region".equals(data.getCode())) {
region = data.getDictValue();
}
if ("Bucket".equals(data.getCode())) {
bucket = data.getDictValue();
}
if ("SecretKey".equals(data.getCode())) {
secretKey = data.getDictValue();
}
if ("SecretId".equals(data.getCode())) {
secretId = data.getDictValue();
}
}
// 替换为您的云 api 密钥 SecretId
config.put("secretId", secretId);
// 替换为您的云 api 密钥 SecretKey
config.put("secretKey", secretKey);
// 初始化 policy
Policy policy = new Policy();
// 设置域名:
// 如果您使用了腾讯云 cvm可以设置内部域名
//config.put("host", "sts.internal.tencentcloudapi.com");
// 临时密钥有效时长,单位是秒,默认 1800 秒,目前主账号最长 2 小时(即 7200 秒),子账号最长 36 小时(即 129600
config.put("durationSeconds", 1800);
// 换成您的 bucket
config.put("bucket", bucket);
// 换成 bucket 所在地区
config.put("region", region);
// 开始构建一条 statement
Statement statement = new Statement();
// 声明设置的结果是允许操作
statement.setEffect("allow");
/**
* 密钥的权限列表。必须在这里指定本次临时密钥所需要的权限。
* 权限列表请参见 https://cloud.tencent.com/document/product/436/31923
* 规则为 {project}:{interfaceName}
* project : 产品缩写 cos相关授权为值为cos,数据万象(数据处理)相关授权值为ci
* 授权所有接口用*表示,例如 cos:*,ci:*
* 添加一批操作权限 :
*/
statement.addActions(new String[]{
"cos:PutObject",
// 表单上传、小程序上传
"cos:PostObject",
// 分块上传
"cos:InitiateMultipartUpload",
"cos:ListMultipartUploads",
"cos:ListParts",
"cos:UploadPart",
"cos:CompleteMultipartUpload",
// 处理相关接口一般为数据万象产品 权限中以ci开头
// 创建媒体处理任务
"ci:CreateMediaJobs",
// 文件压缩
"ci:CreateFileProcessJobs"
});
/**
* 这里改成允许的路径前缀,可以根据自己网站的用户登录态判断允许上传的具体路径
* 资源表达式规则分对象存储(cos)和数据万象(ci)两种
* 数据处理、审核相关接口需要授予ci资源权限
* cos : qcs::cos:{region}:uid/{appid}:{bucket}/{path}
* ci : qcs::ci:{region}:uid/{appid}:bucket/{bucket}/{path}
* 列举几种典型的{path}授权场景:
* 1、允许访问所有对象"*"
* 2、允许访问指定的对象"a/a1.txt", "b/b1.txt"
* 3、允许访问指定前缀的对象"a*", "a/*", "b/*"
* 如果填写了“*”,将允许用户访问所有资源;除非业务需要,否则请按照最小权限原则授予用户相应的访问权限范围。
*
* 示例授权examplebucket-1250000000 bucket目录下的所有资源给cos和ci 授权两条Resource
*/
statement.addResources(new String[]{
"qcs::cos:" + region + ":uid/" + bucket.split("-")[1] + ":" + bucket + "/*",
"qcs::ci:" + region + ":uid/" + bucket.split("-")[1] + ":bucket/" + bucket + "/*"});
// 把一条 statement 添加到 policy
// 可以添加多条
policy.addStatement(statement);
// 将 Policy 示例转化成 String可以使用任何 json 转化方式,这里是本 SDK 自带的推荐方式
config.put("policy", Jackson.toJsonPrettyString(policy));
Response response = CosStsClient.getCredential(config);
System.out.println(response.credentials.tmpSecretId);
System.out.println(response.credentials.tmpSecretKey);
System.out.println(response.credentials.sessionToken);
return ResponseData.success(response);
} catch (Exception e) {
e.printStackTrace();
throw new IllegalArgumentException("no valid secret !");
}
}
@PostMapping("/sign")
public ResponseData sign(@RequestParam(value = "name") @NotBlank(message = "文件名称不能为空") String name) {
String region = "ap-shanghai";
String bucket = "ddht-1324395003";
String secretKey = "VXZWQPYaedvMC6vovAU3gJ1ogXXdvO1n";
String secretId = "AKIDSBQuX5mAZvHa2jNwSzWE0lNvNuMjA9gC";
SysDictData sysDictData = new SysDictData();
sysDictData.setDictType("storing_param");
List<SysDictData> list = iSysDictDataService.selectDictDataList(sysDictData);
for (SysDictData data : list) {
if ("Region".equals(data.getCode())) {
region = data.getDictValue();
}
if ("Bucket".equals(data.getCode())) {
bucket = data.getDictValue();
}
if ("SecretKey".equals(data.getCode())) {
secretKey = data.getDictValue();
}
if ("SecretId".equals(data.getCode())) {
secretId = data.getDictValue();
}
}
long startTimestamp = System.currentTimeMillis() / 1000;
long endTimestamp = startTimestamp + 30 * 60;
String endTimestampStr = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").
format(endTimestamp * 1000);
String keyTime = startTimestamp + ";" + endTimestamp;
String boundary = "----WebKitFormBoundaryZBPbaoYE2gqeB21N";
// 设置表单的body字段值
Map<String, String> formFields = new HashMap<>();
formFields.put("q-sign-algorithm", "sha1");
formFields.put("key", name);
formFields.put("q-ak", secretId);
formFields.put("q-key-time", keyTime);
// 构造policy参考文档: https://cloud.tencent.com/document/product/436/14690
String policy = "{\n" +
" \"expiration\": \"" + endTimestampStr + "\",\n" +
" \"conditions\": [\n" +
" { \"bucket\": \"" + bucket + "\" },\n" +
" { \"q-sign-algorithm\": \"sha1\" },\n" +
" { \"q-ak\": \"" + secretId + "\" },\n" +
" { \"q-sign-time\":\"" + keyTime + "\" }\n" +
" ]\n" +
"}";
// policy需要base64后算放入表单中
String encodedPolicy = new String(Base64.encodeBase64(policy.getBytes()));
// 设置policy
formFields.put("policy", encodedPolicy);
// 根据编码后的policy和secretKey计算签名
COSSigner cosSigner = new COSSigner();
String signature = cosSigner.buildPostObjectSignature(secretKey,
keyTime, policy);
// 设置签名
formFields.put("q-signature", signature);
String urlStr = "https://" + bucket + ".cos." + region + ".myqcloud.com";
formFields.put("host", urlStr);
formFields.put("bucket", bucket);
formFields.put("region", region);
formFields.put("secretId", secretId);
formFields.put("secretKey", secretKey);
return ResponseData.success(formFields);
}
}