上传凭证

从安全角度考虑,NOS的上传服务都需要进行用户认证,无论是公开桶还是私有桶。因此,用户在使用直传服务的时候也需要构造认证信息。构造认证信息包括构造上传策略和计算上传凭证。下面所用到的AccessKey和SecretKey来进行签名验证,开通服务与AccessKey请参考 访问控制

上传策略

{
  "Bucket" : "doc",
  "Object" : "anne.jpg",
  "Expires" : 1451491200,
  "ObjectSizeMin": 126000,
  "ObjectSizeMax": 128000,
  "MimeLimit": "image/jpeg;image/png"
}
名称描述是否必须
Bucket桶名
Object存储在NOS的对象名
Expires过期时间,(Unix时间),单位:秒
ObjectSizeMin限定上传对象大小的最小值,单位:Byte。对象大小小于该值会被判为上传失败,返回 400状态码
ObjectSizeMax限定上传对象大小的最大值,单位:Byte。对象大小大于该值会被判为上传失败,返回 400状态码
MimeLimit限定用户上传的对象类型。指定本字段值,服务器会根据ContentType指定的对象类型来匹配,如果匹配成功则上传,匹配失败则返回 400 状态码,说明该类型被限制上传。
OverWrite当OverWrite为true时,如存在同名文件则覆盖;反之,如存在则提示该对象已经存在,返回码为409。默认为true。

计算上传凭证

下面是一个最简策略:

{
  "Bucket" : "doc",
  "Object" : "anne.jpg",
  "Expires" : 1451491200,
  "ObjectSizeMin": 126000,
  "ObjectSizeMax": 128000,
  "MimeLimit": "image/jpeg;image/png"
}

我们根据这个上传策略可以进一步构造上传凭证,步骤为:

1.将上传策略转换为json格式

{"Bucket":"doc","Object":"anne.jpg","Expires":1451491200,"ObjectSizeMin": 126000,"ObjectSizeMax": 128000,"MimeLimit": image/jpeg;image/png}

2.对JSON编码的上传策略进行Base64编码,得到待签名字符串

encodedPutPolicy = base64_encode(putPolicy)
例如,对于以上事例,在Base64编码后,将得到:
eyJCdWNrZXQiOiJkb2MiLCJPYmplY3QiOiJhbm5lLmpwZyIsIkV4cGlyZXMiOjE0NTE0OTEyMDAsIk9iamVjdFNpemVNaW4iOiAxMjYwMDAsIk9iamVjdFNpemVNYXgiOiAxMjgwMDAsIm1pbWVMaW1pdCI6IGltYWdlL2pwZWc7aW1hZ2UvcG5nfQ==

3.使用SecertKey对上一步生成的待签名字符串计算HMAC-SHA1签名

sign = hmac_sha256(encodedPutPolicy, "<SecretKey>")

4.对签名进行Base64编码

encodedSign = base64_encode(sign)
例如,假设SecretKey = "SecretKey",则经过hmac_sha256签名并经过Base64编码之后得到:
v8Q5BNIJuEoi6zckOzPuC5hADL4t/zNaecakkk8STuE=

5.最终客户端在上传时,按以下方式填充 “x-nos-token” 头部

UPLOAD AccessKey:encodedSign:encodedPutPolicy

示例

如果上传策略为:{“Bucket”:”doc”,”Object”:”anne.jpg”,”Expires”:1451491200},AccessKey为:b6ff5ed65d1041e9a56e2257a2672990,SecretKey为: ae0208eea57c4bc9bc5754368c06a542.计算后对应的”x-nos-token”为:

UPLOAD b6ff5ed65d1041e9a56e2257a2672990:+SL08gyotpanS0qQdqugiWVdDSlsfrQr6YXUNw0Nkz4=:eyJCdWNrZXQiOiJkb2MiLCJPYmplY3QiOiJhbm5lLmpwZyIsIkV4cGlyZXMiOjE0NTE0OTEyMDB9

示例代码

# -*- coding: utf-8 -*-

import base64
import hmac
import hashlib

accessKey = "your Accesskey"
secretKey = "your SecretKey"
putPolicy = '{"Bucket":"your Bucketname","Object":"your Objectname","Expires":1951491200}'

#签名字符串
encodedPutPolicy = base64.b64encode(putPolicy)

#对签名字符串计算HMAC-SHA256签名
signature = hmac.new(secretKey, encodedPutPolicy, digestmod=hashlib.sha256).digest();

#对签名进行Base64编码
encodedSign = base64.b64encode(signature)
token = "UPLOAD " + accessKey + ":" + encodedSign + ":" + encodedPutPolicy
print token
<?php
  $accessKey = "your Accesskey";
  $secretKey = "your SecretKey";
  $putPolicy = '{"Bucket":"your Bucketname","Object":"your Objectname","Expires":1951491200}';

  #签名字符串
  $encodedPutPolicy = base64_encode($putPolicy);
  #对签名字符串计算HMAC-SHA256签名
  $signature = hash_hmac("sha256", $encodedPutPolicy, $secretKey, true);
  #对签名进行Base64编码
  $encodedSign = base64_encode($signature);
  $token = "UPLOAD ".$accessKey.":".$encodedSign.":".$encodedPutPolicy;
  print $token;
?>

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import net.sf.json.JSONObject;

public class Token {
  public static void main(String[] args){
        String accessKey = "b6ff5ed65d1041e9a56e2257a2672990";
        String secretKey = "ae0208eea57c4bc9bc5754368c06a542";
        JSONObject putPolicy = new JSONObject();
        putPolicy.put("Bucket", "doc");
        putPolicy.put("Object", "anne.jpg");
        putPolicy.put("Expires", 1451491200);   
        String encodedPutPolicy = new String(Base64.encodeBase64(putPolicy.toString().getBytes()));
        try {
             Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
             SecretKeySpec secret_key = new SecretKeySpec(secretKey.getBytes(), "HmacSHA256");
             sha256_HMAC.init(secret_key);

             //对签名字符串计算HMAC-SHA256签名
             String encodedSign = Base64.encodeBase64String(sha256_HMAC.doFinal(encodedPutPolicy.getBytes()));     
             String token = "UPLOAD " + accessKey + ":" + encodedSign + ":" + encodedPutPolicy;
             System.out.println(token);
            }
            catch (Exception e){
             System.out.println("Error");
            }  
    }
}

参数说明:

accessKey的值为用户的Access Key

secretKey的值为用户的Access Secret

Expires的值为超时时间点,需要晚于当前时间点。