325 lines
15 KiB
Java
325 lines
15 KiB
Java
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);
|
||
}
|
||
|
||
}
|