本文主要面向新浪云存儲服務的開發(fā)者,開發(fā)者可通過此文學習如何使用新浪云存儲進行開發(fā)
如前所述,云存儲服務通過使用簽名來驗證及識別訪問者的身份。
如果服務器接收到的請求中的URL是帶有簽名的,則服務器可以判斷該請求是否是具備合法訪問權限的用戶身份;如果簽名驗證通過,則請求合法,執(zhí)行請求所要求的相關操作;反之,則服務器判斷請求不合法,拒絕執(zhí)行相關請求操作,返回錯誤提示信息。
如果請求訪問的是設為公開讀的資源,則如果請求訪問相關資源,則可不帶任何簽名,直接訪問資源對應的URL地址、或者直接對資源進行操作即可。
簽名可通過以下幾種方式生成:
- 通過SDK中的相關方法生成簽名
- 通過管理控制臺的“URL簽名”工具,填寫相關參數(shù),自動生成相關請求的URL簽名
- 根據(jù)下文中簽名算法的具體說明來生成相關簽名
我們的簽名認證分為三種:
后面會分別詳細介紹介紹這三種方式.
Signature = Base64( HMAC-SHA1( '您的SecretAccessKey', UTF-8-Encoding-Of( StringToSign ) ) );
ssig = Signature[5:15]; #截取10位字符, 從第5個開始, 第15個結束
StringToSign = HTTP-Verb + "\n" +
Content-MD5 + "\n" +
Content-Type + "\n" +
Date + "\n" +
CanonicalizedAmzHeaders +
CanonicalizedResource;
簽名值的計算方法是對一個UTF-8的字符串,用你的SecretKey(可以到控制臺獲得)進行HMAC-SHA1加密。
然后把加密結果進行Base64編碼, 并截取10位字符, 從第5個開始, 第15個結束. PHP代碼示例:
$ssig = substr( base64_encode( hash_hmac( "sha1", $stringToSign, $mySecretKey, true ) ), 5, 10 ) ;
StringToSign字符串也需要滿足一定的格式。如上所示,HTTP-Verb
、Content-MD5
、Content-Type
、Date
、CanonicalizedAmzHeaders
、CanonicalizedResource
. 他們都用換行符"\n"進行連接, 下面分別對這些值進行介紹:
表示操作名,即HTTP的請求方式,應該為PUT、GET、DELETE、HEAD和POST中的一種.
StringToSign中Content-MD5
的位置可以是HTTP Request Headers(請求頭)中的 s-sina-sha1 或者 s-sina-md5 或者 Content-MD5的值。
我們推薦使用: Content-MD5,兼容AmazonS3
優(yōu)先級: 如果請求頭中同時出現(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-md5和s-sina-sha1是使用hex編碼的值,Content-MD5是按rfc標準使用base64編碼的值
請求頭中的Content-Type值,如果請求頭中沒有出現(xiàn)則留空(例如:GET、HEAD請求方式的請求頭中是沒有Content-Type的)
請求頭中的Date值, 或者Query String(URL中的參數(shù))中Expires參數(shù)的值(時間戳),代表本次請求的有效時間。
如果請求頭Date和Query String中Expires同時出現(xiàn), 則StringToSign中優(yōu)先使用Expires的值。
請求頭中所有以x-amz-和x-sina-開頭的header,將他們的key轉化為小寫并按順序排列,key和value之間用冒號相連,以換行符“\n”連接和結尾,組成CanonicalizedAmzHeaders
加入StringToSign參與簽名。例如請求頭中包含:
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 = [ "/" + 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
兩種形式:
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
如前所述, 我們通過簽名算法構造了一個簽名(ssig),下面介紹如何使用簽名進行資源的訪問和操作。
我們的簽名認證分為三種:
下面依次介紹:
我們需要在請求頭中加入Authorization,格式為:
Authorization: SINA MyAccessKey:ssig
例如上傳一個文件(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
下載一個文件(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
我們需要增加QueryString(URL參數(shù)):KID和ssig,格式為:
KID=sina,MyAccessKey&ssig=ssig_value
注意: 如果使用URL簽名認證方式,ssig需要進行urlencode編碼,因為base64后會出現(xiàn) “+” 字符
例如上傳一個文件(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
下載一個文件(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指定驗證簽名時,我們需要增加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
例如下載一個文件(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)
請求:
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 ) ;
請求:
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 ) ;
請求:
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 ) ;
請求:
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 ) ;
請求:
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 ) ;
請求:
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 ) ;
請求:
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 ) ;
請求:
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 ) ;
上面這些例子中的URL出現(xiàn)了如:ip
、Expires
等參數(shù),下面介紹一下它們的功能:
# | QueryString | 功能定義 |
---|---|---|
1 | KID | 用戶的身份標示,驗證后將使用該帳號的權限訪問文件,格式: KID=sina,accesskey, 可以在控制臺獲得accesskey, 然后前面帶上"sina," |
2 | Expires | 請求的截止時間(時間戳),限制本次請求必須在給定時間戳前完成。參照簽名算法中的StringToSign:Date說明 |
3 | ssig | 簽名驗證串 |
4 | ip | ip地址驗證限制,可以直接寫授權的ip或啟用時間+授權的ip, 在超過啟動時間時只允許該ip地址的用戶下載. 例如:ip=1396569436,1.2.3. 表示ip地址被限制在1.2.3.網(wǎng)段,并在UNIX時間1396569436后生效 ip=1.2.3.4 表示只有ip為1.2.3.4的用戶可以訪問 |
5 | cheese | 進行cookie驗證,服務器端會讀取由cheese所指定的cookie的值,參照簽名驗證中的Cookie認證方式 |
6 | fn | 下載文件名,當存在該選項時服務器將強行返回Content-Disposition, 如果fn的值不為空,則以該值為文件名,否則會自動截取url的最后一段為文件名 |