找回密码
 立即注册
首页 业界区 业界 阿里云 OSS postObject V4 使用

阿里云 OSS postObject V4 使用

管水芸 昨天 11:55
背景

类似预签名的方式,后端生成了签名和policy, 前端使用表单提交。
提示

如果可以,尽量使用简单的方式,比如前端用accessKeyId+accessKeySecret 的方式直接putObject.但这种方法会暴露secret。
也可以通过自己服务后台上传到aliyun oss. 但这种方式会占用自己服务的带宽。
如果使用post Object 的方式,很麻烦,官方文档也的也不好(写的跟si一样)。调试了1天,帮doubao的帮助下才搞定。
后端代码
  1.     public AliyunOssSignatureView genSignature() throws Exception {
  2.         // 步骤1:创建policy。
  3.         ObjectMapper mapper = new ObjectMapper();
  4.         Map<String, Object> policy = new HashMap<>();
  5.         policy.put("expiration", formatISODateTime());
  6.         List<Object> conditions = new ArrayList<>();
  7.         Map<String, String> bucketCondition = new HashMap<>();
  8.         bucketCondition.put("bucket", bucketName);
  9.         conditions.add(bucketCondition);
  10.         Map<String, String> signatureVersionCondition = new HashMap<>();
  11.         signatureVersionCondition.put("x-oss-signature-version", "OSS4-HMAC-SHA256");
  12.         conditions.add(signatureVersionCondition);
  13.         Map<String, String> credentialCondition = new HashMap<>();
  14.         credentialCondition.put("x-oss-credential", accessKeyId + "/" + formatISODate() +  "/" + region + "/oss/aliyun_v4_request"); // 替换为实际的 access key id
  15.         conditions.add(credentialCondition);
  16.         Map<String, String> dateCondition = new HashMap<>();
  17.         dateCondition.put("x-oss-date", formateDateTimeZ());
  18.         conditions.add(dateCondition);
  19.         conditions.add(Arrays.asList("content-length-range", 1L, 1024L*1024*1024*5));
  20.         conditions.add(Arrays.asList("eq", "$success_action_status", "201"));
  21. //        conditions.add(Arrays.asList("starts-with", "$key", "user/eric/"));
  22. //        conditions.add(Arrays.asList("in", "$content-type", Arrays.asList("image/jpg", "image/png")));
  23. //        conditions.add(Arrays.asList("not-in", "$cache-control", Arrays.asList("no-cache")));
  24.         policy.put("conditions", conditions);
  25.         String jsonPolicy = mapper.writeValueAsString(policy);
  26.         // 步骤2:构造待签名字符串(StringToSign)。
  27.         String stringToSign = new String(Base64.encodeBase64(jsonPolicy.getBytes()));
  28.         // 步骤3:计算SigningKey。
  29.         byte[] dateKey = hmacsha256(("aliyun_v4" + accessKeySecret).getBytes(), formatISODate());
  30.         byte[] dateRegionKey = hmacsha256(dateKey, region);
  31.         byte[] dateRegionServiceKey = hmacsha256(dateRegionKey, "oss");
  32.         byte[] signingKey = hmacsha256(dateRegionServiceKey, "aliyun_v4_request");
  33.         // 步骤4:计算Signature。
  34.         byte[] result = hmacsha256(signingKey, stringToSign);
  35.         String signature = BinaryUtil.toHex(result);
  36.         log.info("policy:{}, base64 policy:{}, signature:{}", jsonPolicy, stringToSign, signature);
  37.         return new AliyunOssSignatureView(stringToSign, signature);
  38.     }
  39. public static byte[] hmacsha256(byte[] key, String data) {
  40.         try {
  41.             // 初始化HMAC密钥规格,指定算法为HMAC-SHA256并使用提供的密钥。
  42.             SecretKeySpec secretKeySpec = new SecretKeySpec(key, "HmacSHA256");
  43.             // 获取Mac实例,并通过getInstance方法指定使用HMAC-SHA256算法。
  44.             Mac mac = Mac.getInstance("HmacSHA256");
  45.             // 使用密钥初始化Mac对象。
  46.             mac.init(secretKeySpec);
  47.             // 执行HMAC计算,通过doFinal方法接收需要计算的数据并返回计算结果的数组。
  48.             byte[] hmacBytes = mac.doFinal(data.getBytes());
  49.             return hmacBytes;
  50.         } catch (Exception e) {
  51.             throw new RuntimeException("Failed to calculate HMAC-SHA256", e);
  52.         }
  53.     }
  54.     /**
  55.      * 获取ISO格式时间
  56.      * 2024-12-03T13:00:00Z
  57.      * @return current time iso format
  58.      */
  59.     public static String formatISODateTime() {
  60.         ZonedDateTime utcTime = ZonedDateTime.now();
  61.         utcTime = utcTime.plusHours(1);
  62.         return utcTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"));
  63.     }
  64.     public static String formatISODate() {
  65.         LocalDate utcDate = LocalDate.now(ZoneOffset.UTC);
  66.         return utcDate.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
  67.     }
  68.     public static String formateDateTimeZ() {
  69.         ZonedDateTime utcTime = ZonedDateTime.now(ZoneOffset.UTC);
  70.         return utcTime.format(DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss'Z'"));
  71.     }
复制代码
其中region 一定要注意,是类似cn-beijing 这样的,而不是oss-cn-beijing.
endpoint 是 https://bucketName.oss-cn-beijing.alyuncs.com
上面使用的base64是apache 的。不是java自带的
 
 
前端代码

 
filed的顺序一定不能错,错了就不好使
1.png

 policy 和 x-oss-signature 都是后端生成返回给前端。
key 是上传后的文件名称
前端可以把policy base64 decode一下。在里面取x-oss-signature-version,x-oss-credential, x-oss-date,success_action_status这些值 。
file 是要上传的文件
 
参考文档

https://help.aliyun.com/zh/oss/developer-reference/postobject
https://help.aliyun.com/zh/oss/developer-reference/signature-version-4-recommend?spm=a2c4g.11186623.0.0.700a713f3JNlJV#79752ac45behk
 

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册