阿里云_OSS_URL签名算法_Node版

前言

无论是在app中播放视频,还是在网页上嵌入视频,我们都希望该视频只能在自家的网站或者app中才可以被下载或者被观看

为了防止视频被盗链,我们除了在请求头Header里使用Authorization字段防盗链之外,还可以在URL中加入签名信息

这样我们就还可以把该视频文件的URL分享给其他人,并且实现限时授权访问了


用户签名验证机制

OSS通过使用AccessKeyId / AccessKeySecret对称加密的方法来验证某个请求的发送者身份。

AccessKeyId用于标示用户,

AccessKeySecret是用户用于加密签名字符串和OSS用来验证签名字符串的密钥,其中AccessKeySecret必须保密,只有用户和OSS知道。


AccessKey 根据所属账号的类型有所区分

阿里云账户AccessKey:每个阿里云账号提供的AccessKey拥有对拥有的资源有完全的权限 (慎用)

★  RAM账户AccessKey:RAM账户由阿里云账号授权生成,所拥的AccessKey拥有对特定资源限定的操作权限(推荐)

STS临时访问凭证:由阿里云账号或RAM账号生成,所拥的AccessKey在限定时间内拥有对特定资源限定的操作权限。过期权限收回。


验证思路:

1. 当用户想以个人身份向OSS发送请求时,需要首先将发送的请求按照OSS指定的格式生成签名字符串;

2. 然后使用AccessKeySecret对签名字符串进行加密产生验证码。

3. OSS收到请求以后,会通过AccessKeyId找到对应的AccessKeySecret,以同样的方法提取签名字符串和验证码,如果计算出来的验证码和提供的一样即认为该请求是有效的;

否则,OSS将拒绝处理这次请求,并返回HTTP 403错误。


URL最终效果示例:

http://beyond-cubic.oss-cn-hangzhou.aliyuncs.com/video_01.mp4?OSSAccessKeyId=你的KeyId&Expires=1141889120&Signature=FX6Xd69gednlZ7Ga%2BIYNEm5NWos%3D

http://beyond-cubic.oss-cn-hangzhou.aliyuncs.com/video_01.mp4?
OSSAccessKeyId = 你的KeyId
&
Expires = 1141889120
&
Signature = FX6Xd69gednlZ7Ga%2BIYNEm5NWos%3D


URL签名解释说明:

URL签名,必须至少包含OSSAccessKeyIdExpiresSignature三个参数。

★  OSSAccessKeyId 即密钥中的AccessKeyId。

★  Expires 这个参数的值是一个UNIX时间(自UTC时间1970年1月1号开始的秒数),一般是当前时间戳 + 200秒,用于标识该URL的超时时间。如果OSS接收到这个URL请求的时候晚于签名中包含的Expires参数时,则返回请求超时的错误码,即200秒后,该下载的url链接自动失效。

例如:当前时间是1535816060,开发者希望创建一个60秒后自动失效的URL,则可以设置Expires时间为1535816120。即: 该分享的下载链接只在1分钟内有效

★  Signature 表示签名信息。所有的OSS支持的请求 和 各种Header参数,在URL中进行签名的算法 和 在Header中包含签名的算法基本一样。


签名算法实现原理:

Signature = urlencode(base64(hmac-sha1(AccessKeySecret,
          VERB + "\n" 
          + CONTENT-MD5 + "\n" 
          + CONTENT-TYPE + "\n" 
          + EXPIRES + "\n" 
          + CanonicalizedOSSHeaders
          + CanonicalizedResource)))

但是, 相比在Header中的签名验证, 普通的GET url 签名, 就简单得多了: 

Signature = base64(hmac-sha1(VERB + "\n"
+ "" + "\n"
+ "" + "\n"
+ Expires + "\n"
+ ""
+ CanonicalizedResource))

注意:
VERB就是“GET”或者”PUT”等

CanonicalizedResource就是/beyond-cubic/video_01.mp4之类,

/beyond-cubic是bucket的名称;

/video_01.mp4才是资源的路径


区别对比:

与在请求头header中包含签名的方式相比, URL中签名的主要不同点如下:

★  通过URL包含签名时,之前的Date参数换成Expires参数。

★  不支持同时在URL和Head中包含签名。

★  OSS服务器会先验证请求时间是否晚于Expires时间,然后再验证签名。

★  将签名字符串放到url时,注意要对url进行urlencode

★  如果传入的Signature,Expires,OSSAccessKeyId出现不止一次,以第一次为准。


  • 临时用户URL签名时???,需要携带security-token这个暂时没有用到
  • 格式如下:
    http://oss-example.oss-cn-hangzhou.aliyuncs.com/oss-api.pdf?OSSAccessKeyId=nz2pc56s936**9l&Expires=1141889120&Signature=vjbyPxybdZaNmGa%2ByT272YEAiv4%3D&security-token=SecurityToken

Python示例代码

URL中添加签名的python示例代码

注意: 下面的文件路径必须带在bucket名称喔~

比如: CanonicalizedResource = “/beyond-cubic/video_01.mp4”

bucket名称: /beyond-cubic

资源路径:  /video_01.mp4


signature.py文件里的完整代码如下:

#!/usr/bin/python
# -*- coding: UTF-8 -*-
# 未闻花名 vwhm.net

import base64
import hmac
import sha
import urllib
h = hmac.new("AccessKeySecret",
             "GET\n\n\n1535819709\n/beyond-cubic/video_01.mp4",
             sha)
signature = urllib.quote (base64.encodestring(h.digest()).strip())
print signature

打开终端,生成并打印签名 signature:
>>> python signature.py
>>> FX6Xd69gednlZ7Ga%2BIYNEm5NWos%3D

最终url地址如下:

http://beyond-cubic.oss-cn-shenzhen.aliyuncs.com/cubic_00.mp4?Expires=1535819709&OSSAccessKeyId=你的KeyId&Signature=FX6Xd69gednlZ7Ga%2BIYNEm5NWos%3D

细节分析

★  使用在URL中签名的方式,会将你授权的数据在过期时间以内曝露在互联网上,请预先评估使用风险。

★  PUT和GET请求都支持在URL中签名。

★  在URL中添加签名时,Signature,Expires,OSSAccessKeyId顺序可以交换,但是如果Signature,Expires,OSSAccessKeyId缺少其中的一个或者多个,返回403 Forbidden。错误码:AccessDenied。

★  如果访问的当前时间晚于请求中设定的Expires时间,返回403 Forbidden。错误码:AccessDenied。
如果Expires时间格式错误,返回403 Forbidden。错误码:AccessDenied。

★  如果URL中包含参数Signature,Expires,OSSAccessKeyId中的一个或者多个,并且Head中也包含签名消息,返回消息400 Bad Request。即不支持Url和Head同时验证! 错误码:InvalidArgument。

★  生成签名字符串时,除Date被替换成Expires参数外,仍然包含content-type、content-md5等上节中定义的Header(只是为空罢了)(请求中虽然仍然有Date这个请求头,但不需要将Date加入签名字符串中)。


附录: 其他语言的SDK参考链接:

上面为Python语言,URL签名实现代码
OSS SDK中同时提供了以下六种URL签名的实现代码:
SDK 方法 文件链接
Java OSSClient.generatePresignedUrl OSSClient.java
Python Bucket.sign_url api.py
.Net OssClient.GeneratePresignedUri OssClient.cs
PHP OssClient.signUrl OssClient.php
JS signatureUrl object.js
C oss_gen_signed_url oss_object.c