============ **访问控制** ============ 用户签名验证(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中: