SignatureDoesNotMatch REST接口 在任何时间、任何地点、任何互联网设备上 在Header中包含签名
PutObject_关于Object操作_API 参考_对象存储 OSS-阿里云 https://help.aliyun.com/document_detail/31978.html
OSS API 文档简介_API 参考_对象存储 OSS-阿里云 https://help.aliyun.com/document_detail/31947.html?spm=a2c4g.11186623.6.897.0e87Ue
阿里云对象存储服务(Object Storage Service,简称OSS),是阿里云对外提供的海量、安全、低成本、高可靠的云存储服务。您可以通过本文档提供的简单的REST接口,在任何时间、任何地点、任何互联网设备上进行上传和下载数据。基于OSS,您可以搭建出各种多媒体分享网站、网盘、个人和企业数据备份等基于大规模数据的服务。
<?xml version="1.0" encoding="UTF-8"?>
<Error>
<Code>SignatureDoesNotMatch</Code>
<Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>
<RequestId>5B5421A9F3999E8E590FAAAE</RequestId>
<HostId>myBucket.oss-cn-hangzhou.aliyuncs.com</HostId>
<OSSAccessKeyId>LTAIP7myOQnOabc</OSSAccessKeyId>
<SignatureProvided>JQjm1FNFwAjalykg1I33bOp0bYo=</SignatureProvided>
<StringToSign>PUT video/mpeg4
Sun, Jul :: GMT
/myBucket/uploads/video//testVqhua.mp4</StringToSign>
<StringToSignBytes> 0A 0A 6F 2F 6D 0A 6E 2C 4A 6C 3A 3A 4D 0A 2F 6D 2D 2F 6C 6F 2F 6F 2F 2F 2E 6D </StringToSignBytes>
</Error>
from oss2 import utils # 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建RAM账号。
kid, ks = 'kid', 'ks'
url = 'https://myBucket.oss-cn-hangzhou.aliyuncs.com'
bucket_name = 'myBucket' from oss2.http import Request method, url = 'PUT', url
req = Request(method, url)
req.headers['Date'],req.headers['Content-Type'] =utils.http_date(), 'video/mpeg4' res_d = {}
res_d['Host'],res_d['method'], res_d['Date'], res_d['Content-Type'] =url.split('/')[-1], method, req.headers['date'], 'video/mpeg4' '''
前端提交文件名
key是oss中bucket_name下的文件通用资源标志符(Universal Resource Identifier)
例如:
https://myBucket.oss-cn-hangzhou.aliyuncs.com/uploads/video/26/test10sBM.mp4
则此处key=uploads/video/26/test10sBM.mp4,注意/
该key字符串参与加密计算,utf-8字符串
'''
key = 'uploads/video/26/testVqhua.mp4'
key = 'uploads/video/26/123.mp4'
res_d['OSS-Key']=key
from oss2.auth import *
import urllib '''
直接调用官方类的签名计算方法
''' class myAuthV2(object):
"""签名版本2,与版本1的区别在:
1. 使用SHA256算法,具有更高的安全性
2. 参数计算包含所有的HTTP查询参数
""" def __init__(self, access_key_id, access_key_secret):
self.id = access_key_id.strip()
self.secret = access_key_secret.strip() def my__make_signature(self, req, bucket_name, key, additional_headers=[]):
'''
核心代码
:param req:
:param bucket_name:
:param key:
:param additional_headers:
:return:
'''
print(req, bucket_name, key)
string_to_sign = self.__get_string_to_sign(req, bucket_name, key, additional_headers)
h = hmac.new(to_bytes(self.secret), to_bytes(string_to_sign), hashlib.sha1)
return utils.b64encode_as_string(h.digest()) def __get_additional_headers(self, req, in_additional_headers):
# we add a header into additional_headers only if it is already in req's headers. additional_headers = set(h.lower() for h in in_additional_headers)
keys_in_header = set(k.lower() for k in req.headers.keys()) return additional_headers & keys_in_header def __get_string_to_sign(self, req, bucket_name, key, additional_header_list):
verb = req.method
content_md5 = req.headers.get('content-md5', '')
content_type = req.headers.get('content-type', '')
date = req.headers.get('date', '')
canonicalized_oss_headers = self.__get_canonicalized_oss_headers(req, additional_header_list)
additional_headers = ';'.join(sorted(additional_header_list))
canonicalized_resource = self.__get_resource_string(req, bucket_name, key)
canonicalized_resource = urllib.parse.unquote(canonicalized_resource) print(date)
print('---->')
print(verb + '\n' + \
content_md5 + '\n' + \
content_type + '\n' + \
date + '\n' + \
canonicalized_oss_headers + \
additional_headers + '\n' + \
canonicalized_resource)
print('<----')
print(canonicalized_resource)
# return verb + '\n' +\
# content_md5 + '\n' +\
# content_type + '\n' +\
# date + '\n' +\
# canonicalized_oss_headers +\
# additional_headers + '\n' +\
# canonicalized_resource
print('---->加密字符串,与阿里后台的加密字符串比对,一致,则加密成功')
print('此处对加密参数个数相对原官方包做了删减')
print(verb + '\n' + \
content_md5 + '\n' + \
content_type + '\n' + \
date + '\n' + canonicalized_resource)
print('<----')
return verb + '\n' + \
content_md5 + '\n' + \
content_type + '\n' + \
date + '\n' + canonicalized_resource def __get_resource_string(self, req, bucket_name, key):
if bucket_name:
encoded_uri = v2_uri_encode('/' + bucket_name + '/' + key)
else:
encoded_uri = v2_uri_encode('/') logging.info('encoded_uri={0} key={1}'.format(encoded_uri, key)) return encoded_uri + self.__get_canonalized_query_string(req) def __get_canonalized_query_string(self, req):
encoded_params = {}
for param, value in req.params.items():
encoded_params[v2_uri_encode(param)] = v2_uri_encode(value) if not encoded_params:
return '' sorted_params = sorted(encoded_params.items(), key=lambda e: e[0])
return '?' + '&'.join(self.__param_to_query(k, v) for k, v in sorted_params) def __param_to_query(self, k, v):
if v:
return k + '=' + v
else:
return k def __get_canonicalized_oss_headers(self, req, additional_headers):
"""
:param additional_headers: 小写的headers列表, 并且这些headers都不以'x-oss-'为前缀.
"""
canon_headers = [] for k, v in req.headers.items():
lower_key = k.lower()
if lower_key.startswith('x-oss-') or lower_key in additional_headers:
canon_headers.append((lower_key, v)) canon_headers.sort(key=lambda x: x[0]) return ''.join(v[0] + ':' + v[1] + '\n' for v in canon_headers) res = myAuthV2(kid, ks).my__make_signature(req, bucket_name, key)
print(res)
print('OSS ' + kid + ':' + res)
res_d['Authorization'] = 'OSS ' + kid + ':' + res
res_d['Content-MD5']=''
'''
对前端返回res_d,前端严格按照res_d发起构造header,发起http请求
'''
print(res_d)
前端提供 系统文件系统中的文件名 123.mp4
调用官方包的目的是直接引用官方包中已有的独立的加密库
和官方加密算法中的辅助函数
在Header中包含签名
更新时间:2018-06-08 18:10:25
用户可以在HTTP请求中增加 Authorization
的Header来包含签名(Signature)信息,表明这个消息已被授权。
Authorization字段计算的方法
Authorization = "OSS " + AccessKeyId + ":" + Signature
Signature = base64(hmac-sha1(AccessKeySecret,
VERB + "\n"
+ Content-MD5 + "\n"
+ Content-Type + "\n"
+ Date + "\n"
+ CanonicalizedOSSHeaders
+ CanonicalizedResource))
AccessKeySecret
表示签名所需的密钥VERB
表示HTTP 请求的Method,主要有PUT,GET,POST,HEAD,DELETE等\n
表示换行符Content-MD5
表示请求内容数据的MD5值,对消息内容(不包括头部)计算MD5值获得128比特位数字,对该数字进行base64编码而得到。该请求头可用于消息合法性的检查(消息内容是否与发送时一致),如”eB5eJF1ptWaXm4bijSPyxw==”,也可以为空。详情参看RFC2616 Content-MD5Content-Type
表示请求内容的类型,如”application/octet-stream”,也可以为空Date
表示此次操作的时间,且必须为GMT格式,如”Sun, 22 Nov 2015 08:16:38 GMT”CanonicalizedOSSHeaders
表示以 x-oss- 为前缀的http header的字典序排列CanonicalizedResource
表示用户想要访问的OSS资源
其中,Date和CanonicalizedResource不能为空;如果请求中的Date时间和OSS服务器的时间差15分钟以上,OSS服务器将拒绝该服务,并返回HTTP 403错误。
SignatureDoesNotMatch REST接口 在任何时间、任何地点、任何互联网设备上 在Header中包含签名的更多相关文章
- Linux之时间、地点、人物、事件、情节
时间 date 显示当前时间 time cmd 显示 cmd的运行时间 地点 locate 根据文件名,迅速找到文件.基于系统构建的索引 find 根据各种规则找到文件,更强大,但比较慢 wherei ...
- python接口自动化(三十九)- logger 日志 - 上(超详解)
简介 Python的logging模块提供了通用的日志系统,可以方便第三方模块或者是应用使用.这个模块提供不同的日志级别,并可以采用不同的方式记录日志,比如文件,HTTP GET/POST,SMTP, ...
- C# 用SoapUI调试WCF服务接口(WCF中包含用户名密码的验证)
问题描述: 一般调试wcf程序可以直接建一个单元测试,直接调接口. 但是,这次,我还要测试在接口内的代码中看接收到的用户名密码是否正确,所以,单一的直接调用接口方法行不通, 然后就想办法通过soapU ...
- ASP.NET播客(留言时间,投票IP,留言限字数,上传视频)
留言发布时间功能: 界面: 前台代码: 在Datalist控件中: 在<%#getIsDate(Convert.ToString(Eval("issuanceDate"))) ...
- 程序员的一生时间90%是用在编程上,而剩余的10%是活在世界上。刚进CSDN的博客看到这么句话
程序员的一生时间90%是用在编程上,而剩余的10%是活在世界上. 而自己呢?是个程序员呢还是个业余玩家!
- react native-调用react-native-fs插件时,如果数据的接口是需要验证信息的,在android上运行报错
调用react-native-fs插件时,如果数据的接口是需要验证信息的,在android上运行报错,而在iOS上运行没问题.原因是因为接口是有验证信息的,而调用这个插件时没有传入,在iOS上会自动加 ...
- 简单的股票信息查询系统 1 程序启动后,给用户提供查询接口,允许用户重复查股票行情信息(用到循环) 2 允许用户通过模糊查询股票名,比如输入“啤酒”, 就把所有股票名称中包含“啤酒”的信息打印出来 3 允许按股票价格、涨跌幅、换手率这几列来筛选信息, 比如输入“价格>50”则把价格大于50的股票都打印,输入“市盈率<50“,则把市盈率小于50的股票都打印,不用判断等于。
'''需求:1 程序启动后,给用户提供查询接口,允许用户重复查股票行情信息(用到循环)2 允许用户通过模糊查询股票名,比如输入“啤酒”, 就把所有股票名称中包含“啤酒”的信息打印出来3 允许按股票价格 ...
- dart系列之:时间你慢点走,我要在dart中抓住你
目录 简介 DateTime Duration 总结 简介 时间和日期是我们经常会在程序中使用到的对象.但是对时间和日期的处理因为有不同时区的原因,所以一直以来都不是很好用.就像在java中,为时间和 ...
- clock_gettime接口和linux时间系统
RTC/OSCRTC,Real Time Clock,真实时钟,也叫做CMOS时钟,又叫walltimeOSC,Operation System Clock,系统时钟.在开机时操作系统取得RTC中的时 ...
随机推荐
- 【bzoj2901】矩阵求和 前缀和
题目描述 给出两个n*n的矩阵,m次询问它们的积中给定子矩阵的数值和. 输入 第一行两个正整数n,m. 接下来n行,每行n个非负整数,表示第一个矩阵. 接下来n行,每行n个非负整数,表示第二个矩阵. ...
- [luoguP2053] [SCOI2007]修车(最小费用最大流)
传送门 网络流的建图真的好难! 将一个点拆分成多个点的思想还需要加强. 题解 代码和题解中的图略不一样. #include <queue> #include <cstdio> ...
- FZU 2186 小明的迷宫 【压状dp】
Problem Description 小明误入迷宫,塞翁失马焉知非福,原来在迷宫中还藏着一些财宝,小明想获得所有的财宝并离开迷宫.因为小明还是学生,还有家庭作业要做,所以他想尽快获得所有财宝并离开迷 ...
- 济南学习 Day 5 T3 am
[题目描述] 众所不知,rly现在不会玩国际象棋.但是,作为一个OIer,rly当然做过八皇后问题.在这里再啰嗦几句,皇后可以攻击到同行同列同对角线,在 n*n的棋盘中,摆放n个皇后使它们互相不能攻击 ...
- HDU 5001 Walk (暴力、概率dp)
Walk Time Limit: 30000/15000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Total Sub ...
- OC-为何用copy修饰block
简单来说,block就像一个函数指针,指向我们要使用的函数. 就和函数调用一样的,不管你在哪里写了这个block,只要你把它放在了内存中(通过调用存在这个block的方 法或者是函数),不管放在栈中还 ...
- android widgets控件
1.TextView 类似,C#里的lable,显示一段文本 <TextView android:id="@+id/textView2" android:layout_wid ...
- ROS下使用ASUS Xtion Pro Live
一.ROS官网hydro版本OpenNI安装 3. Installation 3.1 Ubuntu installation To install only openni_camera: sudo a ...
- 什么是Hadoop?什么是HDFS?
[学习笔记] 什么是Hadoop?什么是HDFS?马 克-to-win @ 马克java社区:Hadoop是Apache基金会开发的一个分布式系统基础架构.比如前面我们接触的Spring就是一个开发应 ...
- Java中ArrayList类
ArratList 类:存放同一数据类型容器(只能为引用数据类型,因实际其内部存放的是地址) 1.导入其所在包 import java.util.ArratList 2.创建对象 ArrayList& ...