============
**访问控制**
============
用户签名验证(Authentication)
==============================
NOS通过使用访问凭证ID(`AccessKey `_)/访问凭证密钥(SecretKey)非对称加密的方法来验证某
个请求的发送者身份。AccessKey用于标识用户,SecretKey是用户用于加密签名字符串和NOS
用来验证签名字符串的密钥,其中SecretKey必须保密,只有用户和NOS知道。每个访问凭证
对都有active/inactive两种状态
- active表明用户可以用此ID对签名验证请求
- inactive表明用户暂停此ID对签名验证的功能
一个用户可以同时拥有多个active或者inactive的ID对。用户可以登录API KEY管理页面查看
管理访问凭证。当用户想以个人身份向NOS发送请求时,需要首先将发送的请求按照NOS指定
的格式生成签名字符串;然后使用SecretKey对签名字符串进行加密产生验证码。NOS收到请
求以后,会通过AccessKey找到对应的SecretKey,以同样的方法提取签名字符串和验证码,
如果计算出来的验证码和提供的一样即认为该请求是有效的;否则,NOS将拒绝处理这次请求
,并返回相关的错误码。例如若AccessKey格式有误,返回错误码:InvalidAccessKeyId。
在Head中包含签名
================
用户可以在HTTP请求头中增加Authorization(授权)来包含签名信息,表明这个请求已被授
权。如果用户的请求中没有Authentication字段,则认为是匿名访问。
验证码计算
----------
.. code:: java
"Authorization: NOS " + AccessKey + ":" + Base64(HMAC-SHA256(HTTP-Verb + "\n"
+ Content-MD5 + "\n"
+ Content-Type + "\n"
+ Date + "\n"
+ CanonicalizedHeaders
+ CanonicalizedResource))
- HTTP-Verb表示HTTP请求类型,如:PUT,GET,DELETE等
- Content-MD5表示内容数据的MD5值,某些API该字段非必须
- Content-Type表示内容的类型,某些API该字段非必须
- Date表示此次操作的时间,格式必须符合RFC1123的日期格式,示例:Wed, 01 Mar 2009 12:00:00 GMT
- CanonicalizedHeaders 表示请求中其他重要的HTTP头,构建方法见3.2.2节
- CanonicalizedResource 表示用户想要访问的NOS资源,构建方法见3.2.3节
其中,Date和CanonicalizedResource不能为空,其余字段如为空,用空字符串\ ``""``\ 代
替;如果请求中的Date时间和NOS服务器的时间差正负15分钟以上,NOS服务器将拒绝该服务
,并返回错误码:AccessDenied。
构建CanonicalizedHeaders的方法
------------------------------
所有以"x-nos-"为前缀的HTTP Header被称为CanonicalizedHeaders。它的构建方法如下:
#. 将所有以"x-nos-"为前缀的HTTP请求头的key转换成小写字母。如"x-nos-meta-Name: Easyread"转换成"x-nos-meta-name: Easyread"。
#. 如果有相同名字的请求头,则根据标准RFC 2616, 4.2章进行合并(两个值之间只用逗号分隔)。如有两个名为"x-nos-meta-name"的请求头,对应的值分别为"photo"和"Easyread",则合并后为:"x-nos-meta-name:photo,Easyread"。*注意:合并之后的顺序和请求头中出现的顺序一致*
#. 将上一步得到的所有HTTP请求头按照字典序进行升序排列。
#. 删除请求头和内容之间分隔符两端出现的任何空格。如"x-nos-meta-name : photo,Easyread"转换成:"x-nos-meta-name:photo,Easyread"。
#. 将所有的头和内容用\ ``"\n"``\ 分隔符分隔拼成最后的CanonicalizedHeader。
构建CanonicalizedResource的方法
-------------------------------
用户发送请求中想访问的NOS目标资源被称为CanonicalizedResource。它的构建方法如下:
- 将CanonicalizedResource置成空字符串\ ``""``\ ;
- 放入要访问的NOS资源:对于ListBucket操作,资源为/;对于桶操作,资源为/BucketName/;对于对象操作,资源为/BucketName/ObjectName;
- 如果请求包含子资源(sub-resource),那么将所有子资源的Key按照字典序排列,并以"&"为分隔符生成子资源字符串。在CanonicalizedResource字符串尾添加"?"和子资源字符串。示例:/BucketName/ObjectName?partNumber=PartNumber&uploadId=UploadId
.. ATTENTION:: sub-resource,指的是NOS里面某些特殊的请求参数。NOS当前支持的子资源包括:"acl", "location", "uploadId", "uploads", "partNumber", "delete"等
在计算签名头的时候请遵循如下规则
--------------------------------
#. 用来签名的字符串为UTF-8格式,URL中的resource和queryString应该经过URL encode。
#. 签名的方法用\ `RFC 2104 `_\ 中定义的HMAC-SHA256方法,其中Key为Secretkey。
#. Content-Type和Content-MD5在请求中不是必须的,但是如果请求需要签名验证,\ **空值的话以回车符代替**\ 。
#. 在所有非HTTP标准定义的header中,以"x-nos-"开头的header,都需要加入签名字符串。
#. 以"x-nos-"开头的header在签名验证前需要符合以下规范:
- header的名字需要变成小写。
- header按字典序自小到大排序。
- 分割header name和value的冒号前后不能有空格。
- 每个Header之后都有一个回车,如果没有Header,CanonicalizedHeaders就设置为空。
注意事项
--------
#. 如果传入的AccessKey不存在或inactive,返回403 Forbidden。错误码:InvalidAccessKeyId。
#. 若用户请求头中Authorization值的格式不对,返回403 Forbidden。错误码:InvalidAccessKeyId。
#. 如果签名验证的时候,请求头中没有传入Date或者格式不正确,返回403 Forbidden错误。错误码:AccessDenied。
#. 传入请求的时间必须在NOS服务器当前时间之后的15分钟以内,否则返回403 Forbidden。错误码:RequestTimeTooSkewed。
#. 如果AccessKey是active的,但NOS判断用户的请求发生签名错误,则返回403 Forbidden,错误码AccessDenied。
#. 计算签名的逻辑,可参看各类SDK源码 。
在URL中包含签名
===============
除了使用Authorization Header Http 头部之外,私有桶的访问外链用户还可以在URL中加入
签名信息,这样用户就可以把私有桶资源,以签名HTTP URL方式转给第三方实现授权访问。
URL中包含签名示例
-----------------
.. code:: java
http://nos.netease.com/myBucket/myObject?NOSAccessKeyId=b65d532bf4834789b5d38e394b47023d&Expires=1141889120&Signature=cjrwrMDR6xoP5jajz17ybSjvftQ%3D
在URL中实现签名,必须至少包含\ **Signature**\ ,\ **Expires**\ ,\ **NOSAccessKeyId**\
三个参数。Expires这个参数的值是一个UNIX时间(自UTC时间1970年1月1号开始的秒数),
用于标识该URL的超时时间。如果NOS接收到这个URL请求的时候晚于签名中包含的Expires参
数时,则返回请求超时的错误码。例如:当前时间是114189060,开发者希望创建一个60秒后
自动失效的URL,则可以设置Expires时间为1141889120。
所有NOS支持的请求和各种Header参数,在URL中进行签名的方法和上节介绍的签名算法基
本一样。主要区别如下:
#. 通过URL包含签名时,之前的Date参数换成Expires参数。
#. 对签名串做URL-Encode编码
#. 对URL而言,Content-MD5、Content-Type等都是空串(\ ``""``\ )
.. code:: java
Signature = URL-Encode (Base64(HMAC-SHA256(HTTP-Verb + "\n"
+ Content-MD5 + "\n"
+ Content-Type + "\n"
+ Expires + "\n"
+ CanonicalizedHeaders
+ CanonicalizedResource))
其他注意事项:
#. 不支持同时在URL和Head中包含签名。
#. 如果传入的Signature,Expires,NOSAccessKeyId出现不止一次,以第一次为准。
#. 请求先验证请求时间是否晚于Expires时间,然后再验证签名。
注意事项
--------
#. 使用在URL中签名的方式,会将你授权的数据在过期时间以内曝露在互联网上,请预先评估使用风险。
#. URL签名只支持GET请求下载Object。
#. 在URL中添加签名时,Signature,Expires,NOSAccessKeyId顺序可以交换,但是如果Signature,Expires,NOSAccessKeyId缺少其中的一个或者多个,返回403 Forbidden。错误码:AccessDenied。
#. 如果访问的当前时间晚于请求中设定的Expires时间,返回403 Forbidden。错误码:AccessDenied。
#. 如果传入请求时间,必须在NOS服务器当前时间之后的15分钟以内。否则返回403 Forbidden。错误码:RequestTimeTooSkewed。
#. 如果Expires时间格式错误,返回403 Forbidden。错误码:AccessDenied。
#. 如果URL中包含参数Signature,Expires,NOSAccessKeyId中的一个或者多个,并且Head中也包含签名消息,返回消息400 Bad Request。错误码:InvalidArgument。
#. 生成URL中的签名字符串时,除Date被替换成Expires参数外,仍然包含content-type、content-md5、CanonicalizedHeaders、CanonicalizedResource等上节中定义的Header。(请求中虽然仍然有Date这个请求头,但不需要将Date加入签名字符串中)
Bucket权限控制
==============
NOS提供Bucket级别的权限访问控制,Bucket目前有两种访问权限:Public-read和Private,它们的含义如下:
- **Public-read:**\ 只有该Bucket的创建者可以对该Bucket内的Object进行写操作(包括Put和Delete Object);任何人(包括匿名访问)可以对该Bucket中的Object进行读操作(Get Object)。
- **Private:**\ 只有该Bucket的创建者可以对该Bucket内的Object进行读写操作(包括Put、Delete和Get Object);其他人无法访问该Bucket内的Object。
用户新创建一个Bucket时,如果不指定Bucket权限,NOS会自动为该Bucket设置Private权限。对于一个已经存在的Bucket,只有它的创建者可以修改该Bucket的权限。
Object外链地址的构成规则
========================
如果一个Bucket设置成Public-read权限,意味着你允许其他用户来访问属于你的Object。你的Object的外链地址构成规则如下:
.. code:: java
http://<你的Bucket名字>.endpoint/<你的Object名字>
例如,在一个杭州分区Bucket(名字为photo)中,放了名为一个"image/test.jpg"的Object,那么这个Object的URL为:
.. code:: java
http://photo.nos-eastchina1-i.netease.com/image/test.jpg
photo是Bucket
nos-eastchina1-i.netease.com为杭州分区的访问域名
image/test.jpg是Object
用户可以将该URL链接放入HTML中: