開發(fā)指南

本文主要面向新浪云存儲(chǔ)服務(wù)的開發(fā)者,開發(fā)者可通過此文學(xué)習(xí)如何使用新浪云存儲(chǔ)進(jìn)行開發(fā)

簽名算法

如前所述,云存儲(chǔ)服務(wù)通過使用簽名來驗(yàn)證及識(shí)別訪問者的身份。

如果服務(wù)器接收到的請(qǐng)求中的URL是帶有簽名的,則服務(wù)器可以判斷該請(qǐng)求是否是具備合法訪問權(quán)限的用戶身份;如果簽名驗(yàn)證通過,則請(qǐng)求合法,執(zhí)行請(qǐng)求所要求的相關(guān)操作;反之,則服務(wù)器判斷請(qǐng)求不合法,拒絕執(zhí)行相關(guān)請(qǐng)求操作,返回錯(cuò)誤提示信息。

如果請(qǐng)求訪問的是設(shè)為公開讀的資源,則如果請(qǐng)求訪問相關(guān)資源,則可不帶任何簽名,直接訪問資源對(duì)應(yīng)的URL地址、或者直接對(duì)資源進(jìn)行操作即可。

簽名可通過以下幾種方式生成:

  1. 通過SDK中的相關(guān)方法生成簽名
  2. 通過管理控制臺(tái)的“URL簽名”工具,填寫相關(guān)參數(shù),自動(dòng)生成相關(guān)請(qǐng)求的URL簽名
  3. 根據(jù)下文中簽名算法的具體說明來生成相關(guān)簽名

我們的簽名認(rèn)證分為三種:

  1. HTTP Request Header(Authorization)方式
  2. URL簽名認(rèn)證方式
  3. Cookie認(rèn)證方式

后面會(huì)分別詳細(xì)介紹介紹這三種方式.


簽名的基本形式

Signature = Base64( HMAC-SHA1( '您的SecretAccessKey', UTF-8-Encoding-Of( StringToSign ) ) );

ssig = Signature[5:15]; #截取10位字符, 從第5個(gè)開始, 第15個(gè)結(jié)束

StringToSign = HTTP-Verb + "\n" +
               Content-MD5 + "\n" +
               Content-Type + "\n" +
               Date + "\n" +
               CanonicalizedAmzHeaders +
               CanonicalizedResource;

簽名值的計(jì)算方法是對(duì)一個(gè)UTF-8的字符串,用你的SecretKey(可以到控制臺(tái)獲得)進(jìn)行HMAC-SHA1加密。

然后把加密結(jié)果進(jìn)行Base64編碼, 并截取10位字符, 從第5個(gè)開始, 第15個(gè)結(jié)束. PHP代碼示例:

$ssig = substr( base64_encode( hash_hmac( "sha1", $stringToSign, $mySecretKey, true ) ), 5, 10 ) ;

StringToSign字符串也需要滿足一定的格式。如上所示,HTTP-Verb、Content-MD5Content-Type、Date、CanonicalizedAmzHeadersCanonicalizedResource. 他們都用換行符"\n"進(jìn)行連接, 下面分別對(duì)這些值進(jìn)行介紹:

  • HTTP-Verb:

    表示操作名,即HTTP的請(qǐng)求方式,應(yīng)該為PUT、GET、DELETE、HEAD和POST中的一種.

  • Content-MD5:

    StringToSign中Content-MD5的位置可以是HTTP Request Headers(請(qǐng)求頭)中的 s-sina-sha1 或者 s-sina-md5 或者 Content-MD5的值。

    我們推薦使用: Content-MD5,兼容AmazonS3

    優(yōu)先級(jí): 如果請(qǐng)求頭中同時(shí)出現(xiàn),StringToSign中優(yōu)先使用s-sina-sha1的值,如果沒有出現(xiàn)s-sina-sha1則使用s-sina-md5,s-sina-md5沒有出現(xiàn)則使用Content-MD5

    如果都未出現(xiàn)則留空

    需要注意的是s-sina-md5s-sina-sha1是使用hex編碼的值,Content-MD5是按rfc標(biāo)準(zhǔn)使用base64編碼的值

  • Content-Type:

    請(qǐng)求頭中的Content-Type值,如果請(qǐng)求頭中沒有出現(xiàn)則留空(例如:GET、HEAD請(qǐng)求方式的請(qǐng)求頭中是沒有Content-Type的)

  • Date:

    請(qǐng)求頭中的Date值, 或者Query String(URL中的參數(shù))中Expires參數(shù)的值(時(shí)間戳),代表本次請(qǐng)求的有效時(shí)間。

    如果請(qǐng)求頭Date和Query String中Expires同時(shí)出現(xiàn), 則StringToSign中優(yōu)先使用Expires的值。

  • CanonicalizedAmzHeaders:

    請(qǐng)求頭中所有以x-amz-x-sina-開頭的header,將他們的key轉(zhuǎn)化為小寫并按順序排列,key和value之間用冒號(hào)相連,以換行符“\n”連接和結(jié)尾,組成CanonicalizedAmzHeaders加入StringToSign參與簽名。例如請(qǐng)求頭中包含:

    X-Sina-Meta-FileIcon: page_white_code.png
    X-Amz-Meta-ReviewedBy: test@test.net
    X-Amz-Meta-FileChecksum: 0x02661779
    X-Amz-Meta-CheckSumAlgorithm: crc32

    那么CanonicalizedAmzHeaders為:

    x-amz-meta-checksumalgorithm:crc32\n
    x-amz-meta-filechecksum:0x02661779\n
    x-amz-meta-reviewedby:test@test.net\n
    x-sina-meta-fileicon:page_white_code.png\n
  • CanonicalizedResource:
    
    CanonicalizedResource = [ "/" + Bucket ] +
    	<HTTP-Request-URI, from the protocol name up to the query string> +
    	[ sub-resource, if present. For example ("?acl", "?location", "?torrent", "?website", "?logging", "?relax", "?meta", "?uploads", "?multipart", "?part", "?copy"), or ("?uploadId=...", "ip=...", "partNumber=...")];
    

    CanonicalizedResource是指想要訪問的資源

    如果訪問資源沒有指定bucket,那么CanonicalizedResource = “/”;

    如果包括bucket,而不包括object,那就是“/bucket_name/”,注意前后都帶“/”;

    如果既包括bucket,也包括object,那么就是“/bucket_name/object_name”;

    另外,如果您要訪問的URL中帶有如下的參數(shù), 則需要加入sub-resource參與簽名

    sub-resource兩種形式:

    1. 不帶”=”的querystring參數(shù): "?acl"、 "?location"、 "?torrent"、 "?website"、 "?logging"、 "?relax"、 "?meta"、 "?uploads"、 "?multipart"、 "?part"、 "?copy"。每個(gè)url中最多只能出現(xiàn)1個(gè)不帶”=”的參數(shù)
    2. 帶”=”的key-value形式的參數(shù): "?uploadId=..."、 "ip=..."、 "partNumber=..."。如果querystring里出現(xiàn)前面這些key-value形式的參數(shù),需將所有的key-value參數(shù)按key的字符串升序排序后,追加到后面。

    CanonicalizedResource中帶有sub-resource舉例說明:

    • 含有不帶”=”的querystring參數(shù)(?acl):

      /bucket_name/my_file?acl

    • 含有ip參數(shù):

      /bucket_name/my_file?acl&ip=123.1.2.3

    • 含有ip和uploadID參數(shù):

      /bucket_name/my_file?acl&ip=123.1.2.3&uploadID=abc123

    • 含有ip和uploadID,沒有acl:

      /bucket_name/my_file?ip=123.1.2.3&uploadID=abc123


簽名認(rèn)證

如前所述, 我們通過簽名算法構(gòu)造了一個(gè)簽名(ssig),下面介紹如何使用簽名進(jìn)行資源的訪問和操作。

我們的簽名認(rèn)證分為三種:

  1. HTTP Request Header(Authorization)方式
  2. URL簽名認(rèn)證方式
  3. Cookie認(rèn)證方式

下面依次介紹:

HTTP Request Header(Authorization)方式:

我們需要在請(qǐng)求頭中加入Authorization,格式為:

Authorization: SINA MyAccessKey:ssig

例如上傳一個(gè)文件(AccessKey=1001HBK3UF,ssig=5KABik\k+K):

PUT /file/to/my/file.txt?formatter=json HTTP/1.1
Host: my_bucket.sinacloud.net
x-amz-acl: private
Authorization: SINA 1001HBK3UF:5KABik\k+K
Date: Sat, 20 Nov 2286 17:46:39 GMT
Content-Type: text/plain
Content-Length: 12918291

下載一個(gè)文件(AccessKey=1001HBK3UF,ssig=5KABikASeK):

GET /file/to/my/file.txt?Expires=1396513956&ip=1.2.3.4&formatter=json HTTP/1.1
Host: my_bucket.sinacloud.net
Authorization: SINA 1001HBK3UF:5KABikASeK

URL簽名認(rèn)證方式:

我們需要增加QueryString(URL參數(shù)):KIDssig,格式為:

KID=sina,MyAccessKey&ssig=ssig_value

注意: 如果使用URL簽名認(rèn)證方式,ssig需要進(jìn)行urlencode編碼,因?yàn)閎ase64后會(huì)出現(xiàn) “+” 字符

例如上傳一個(gè)文件(AccessKey=1001HBK3UF,ssig=J4wyCwmznM):

PUT /file/to/my/file.txt?KID=sina,1001HBK3UF&ssig=J4wyCwmznM&Expires=1396515387&ip=1.2.3.4&formatter=json HTTP/1.1
Host: my_bucket.sinacloud.net
x-amz-acl: private
Content-Type: text/plain
Content-Length: 12918291

下載一個(gè)文件(AccessKey=1001HBK3UF,ssig=5KABikASeK):

GET /file/to/my/file.txt?KID=sina,1001HBK3UF&ssig=5KABikASeK&Expires=1396515387&ip=1.2.3.4&formatter=json HTTP/1.1
Host: my_bucket.sinacloud.net

Cookie認(rèn)證方式:

當(dāng)需要使用Cookie指定驗(yàn)證簽名時(shí),我們需要增加QueryString(URL參數(shù)):cheese, 它的值為Cookie的名字。例如:

cheese=cookie_name

Cookie格式為(Cookie中只支持ssig和Expires):

Cookie: cookie_name=urlencode("ssig=ssig_value&Expires=Expires_value")

注意: cookie_name的值和ssig的值,都需要urlencode

例如下載一個(gè)文件(AccessKey=1001HBK3UF,ssig=5KABikASeK):

GET /file/to/my/file.txt?KID=sina,1001HBK3UF&ip=1.2.3.4&formatter=json&cheese=hehe123 HTTP/1.1
Host: my_bucket.sinacloud.net
Cookie: hehe123=urlencode(ssig=5KABikASeK&Expires=1396515387)


典型示例

示例1:list bucket

請(qǐng)求:

GET /?formatter=json HTTP/1.1
Host: sinacloud.net
Date: Sat, 20 Nov 2286 17:46:39 GMT
Authorization: SINA 1001HBKAUX:J4wyCwmznM

簽名:

$stringToSign = "GET" + "\n" + 
		"\n" + 
		"\n" + 
		"Sat, 20 Nov 2286 17:46:39 GMT" + "\n" + 
		"/";
		
$ssig = substr( base64_encode( hash_hmac( "sha1", $stringToSign, $mySecretKey, true ) ), 5, 10 ) ;

請(qǐng)求:

GET /?formatter=json&KID=sina,1001HBKAUX&ssig=J4wyCwmznM&Expires=1396532775 HTTP/1.1
Host: sinacloud.net

簽名:

$stringToSign = "GET" + "\n" + 
		"\n" + 
		"\n" + 
		"1396532775" + "\n" + 
		"/";
		
$ssig = substr( base64_encode( hash_hmac( "sha1", $stringToSign, $mySecretKey, true ) ), 5, 10 ) ;

示例2:列文件

請(qǐng)求:

GET /?formatter=json HTTP/1.1
Host: bucket-name.sinacloud.net
Date: Thu, 03 Apr 2014 13:46:16 GMT
Authorization: SINA 1001HBKAUX:lFcLwnk4C/

簽名:

$stringToSign = "GET" + "\n" + 
		"\n" + 
		"\n" + 
		"Thu, 03 Apr 2014 13:46:16 GMT" + "\n" + 
		"/bucket_name/";
		
$ssig = substr( base64_encode( hash_hmac( "sha1", $stringToSign, $mySecretKey, true ) ), 5, 10 ) ;

示例3:上傳一個(gè)文件

請(qǐng)求:

PUT /path/to/my/file.txt?formatter=json HTTP/1.1
x-amz-acl: private
x-amz-meta-UploadLocation: My Home
Host: bucket_name.sinacloud.net
Date: Thu, 03 Apr 2014 14:00:28 GMT
Content-MD5: htUc53U6NgeQQfwV9ySANQ==
Content-Type: text/plain
Authorization: SINA 1001HBKAUX:Wnc9TJmvVZ

BODY

簽名:

$stringToSign = "PUT" + "\n" + 
		"htUc53U6NgeQQfwV9ySANQ==" + "\n" + 
		"text/plain" + "\n" + 
		"Thu, 03 Apr 2014 14:00:28 GMT" + "\n" + 
		"x-amz-acl:private" + "\n" + "x-amz-meta-uploadlocation:My Home" + "\n" + 
		"/bucket_name/path/to/my/file.txt";

$ssig = substr( base64_encode( hash_hmac( "sha1", $stringToSign, $mySecretKey, true ) ), 5, 10 ) ;

請(qǐng)求:

PUT /path/to/my/file.txt?formatter=json&KID=sina,1001HBKAUX&ssig=J4wyCwmznM&Expires=1396532775 HTTP/1.1
x-amz-acl: private
x-amz-meta-UploadLocation: My Home
Host: bucket_name.sinacloud.net
Content-MD5: htUc53U6NgeQQfwV9ySANQ==
Content-Type: text/plain

BODY

簽名:

$stringToSign = "PUT" + "\n" + 
		"htUc53U6NgeQQfwV9ySANQ==" + "\n" + 
		"text/plain" + "\n" + 
		"1396532775" + "\n" + 
		"x-amz-acl:private" + "\n" + "x-amz-meta-uploadlocation:My Home" + "\n" + 
		"/bucket_name/path/to/my/file.txt";
		
$ssig = substr( base64_encode( hash_hmac( "sha1", $stringToSign, $mySecretKey, true ) ), 5, 10 ) ;

示例4:獲得文件信息

請(qǐng)求:

HEAD /path/to/my/file.txt?formatter=json HTTP/1.1
Host: bucket_name.sinacloud.net
Date: Thu, 03 Apr 2014 14:27:41 GMT
Authorization: SINA 1001HBKAUX:ojecD2wl9d

簽名:

$stringToSign = "HEAD" + "\n" + 
		"\n" + 
		"\n" + 
		"Thu, 03 Apr 2014 14:27:41 GMT" + "\n" + 
		"/bucket_name/path/to/my/file.txt";

$ssig = substr( base64_encode( hash_hmac( "sha1", $stringToSign, $mySecretKey, true ) ), 5, 10 ) ;

示例5:設(shè)置ACL

請(qǐng)求:

PUT /bucket_name/file?acl&formatter=json HTTP/1.1
Host: sinacloud.net
Date: Thu, 03 Apr 2014 14:35:15 GMT
Content-Type: application/json
Authorization: SINA 1001HBKAUX:Or5quZmjRK

BODY

簽名:

$stringToSign = "PUT" + "\n" + 
		"\n" + 
		"application/json" + "\n" + 
		"Thu, 03 Apr 2014 14:35:15 GMT" + "\n" + 
		"/bucket_name/file?acl";

$ssig = substr( base64_encode( hash_hmac( "sha1", $stringToSign, $mySecretKey, true ) ), 5, 10 ) ;

示例6:下載一個(gè)文件

請(qǐng)求:

GET /path/to/my/file.txt?KID=sina,1001hbk3aV&Expires=1396569436&ip=1.2.3.4&ssig=WJdSQWSZEF&fn=custom_file_name.txt HTTP/1.1
Host: bucket-name.sinacloud.net

簽名:

$stringToSign = "GET" + "\n" + 
		"\n" + 
		"\n" + 
		"1396569436" + "\n" + 
		"/bucket_name/path/to/my/file.txt?ip=1.2.3.4";

$ssig = substr( base64_encode( hash_hmac( "sha1", $stringToSign, $mySecretKey, true ) ), 5, 10 ) ;

功能參數(shù)說明

上面這些例子中的URL出現(xiàn)了如:ipExpires等參數(shù),下面介紹一下它們的功能:

#   QueryString 功能定義
1 KID 用戶的身份標(biāo)示,驗(yàn)證后將使用該帳號(hào)的權(quán)限訪問文件,格式: KID=sina,accesskey, 可以在控制臺(tái)獲得accesskey, 然后前面帶上"sina,"
2 Expires 請(qǐng)求的截止時(shí)間(時(shí)間戳),限制本次請(qǐng)求必須在給定時(shí)間戳前完成。參照簽名算法中的StringToSign:Date說明
3 ssig 簽名驗(yàn)證串
4 ip ip地址驗(yàn)證限制,可以直接寫授權(quán)的ip或啟用時(shí)間+授權(quán)的ip, 在超過啟動(dòng)時(shí)間時(shí)只允許該ip地址的用戶下載.
例如:ip=1396569436,1.2.3. 表示ip地址被限制在1.2.3.網(wǎng)段,并在UNIX時(shí)間1396569436后生效
ip=1.2.3.4 表示只有ip為1.2.3.4的用戶可以訪問
5 cheese 進(jìn)行cookie驗(yàn)證,服務(wù)器端會(huì)讀取由cheese所指定的cookie的值,參照簽名驗(yàn)證中的Cookie認(rèn)證方式
6 fn 下載文件名,當(dāng)存在該選項(xiàng)時(shí)服務(wù)器將強(qiáng)行返回Content-Disposition, 如果fn的值不為空,則以該值為文件名,否則會(huì)自動(dòng)截取url的最后一段為文件名