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 config = new TreeMap(); 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 config = new TreeMap(); try { String secretKey = "VXZWQPYaedvMC6vovAU3gJ1ogXXdvO1n"; String secretId = "AKIDSBQuX5mAZvHa2jNwSzWE0lNvNuMjA9gC"; String region = "ap-shanghai"; String bucket = "ddht-1324395003"; SysDictData sysDictData = new SysDictData(); sysDictData.setDictType("storing_param"); List 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 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 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); } }