zoukankan      html  css  js  c++  java
  • 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, 22 Jul 2018 06:09:59 GMT
    /myBucket/uploads/video/123/testVqhua.mp4</StringToSign>
        <StringToSignBytes>50 44 54 0A 0A 76 56 64 65 6F 2F 6D 70 65 67 34 0A 53 75 6E 2C 20 32 32 20 4A 75 6C 20 32 30 31 38 20 30 36 3A 30 39 3A 35 39 20 47 4D 54 0A 2F 62 61 69 6D 61 2D 32 30 31 38 30 35 2F 75 70 6C 6F 61 64 73 2F 76 69 64 65 6F 2F 32 36 2F 74 65 73 74 56 71 68 75 61 2E 6D 70 34 </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 + '
    ' + 
                  content_md5 + '
    ' + 
                  content_type + '
    ' + 
                  date + '
    ' + 
                  canonicalized_oss_headers + 
                  additional_headers + '
    ' + 
                  canonicalized_resource)
            print('<----')
            print(canonicalized_resource)
            # return verb + '
    ' +
            #     content_md5 + '
    ' +
            #     content_type + '
    ' +
            #     date + '
    ' +
            #     canonicalized_oss_headers +
            #     additional_headers + '
    ' +
            #     canonicalized_resource
            print('---->加密字符串,与阿里后台的加密字符串比对,一致,则加密成功')
            print('此处对加密参数个数相对原官方包做了删减')
            print(verb + '
    ' + 
                  content_md5 + '
    ' + 
                  content_type + '
    ' + 
                  date + '
    ' + canonicalized_resource)
            print('<----')
            return verb + '
    ' + 
                  content_md5 + '
    ' + 
                  content_type + '
    ' + 
                  date + '
    ' + 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] + '
    ' 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 + "
    "
                + Content-MD5 + "
    " 
                + Content-Type + "
    " 
                + Date + "
    " 
                + CanonicalizedOSSHeaders
                + CanonicalizedResource))
    • AccessKeySecret 表示签名所需的密钥
    • VERB表示HTTP 请求的Method,主要有PUT,GET,POST,HEAD,DELETE等
    •  表示换行符
    • Content-MD5 表示请求内容数据的MD5值,对消息内容(不包括头部)计算MD5值获得128比特位数字,对该数字进行base64编码而得到。该请求头可用于消息合法性的检查(消息内容是否与发送时一致),如”eB5eJF1ptWaXm4bijSPyxw==”,也可以为空。详情参看RFC2616 Content-MD5
    • Content-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错误。

     

     

     

     

     

     

     

     

     

     

     

  • 相关阅读:
    linux常用命令:
    解决css添加padding后元素变长的问题
    Hbase常用命令
    集群部署的三种方式(hadoop集群部署三种方式)
    linux编译安装指定依赖的软件包
    vue使用Element隐藏侧边栏进度条
    css相对于父容器,固定放在底部并撑满
    java中23种设计模式
    adb remount'的作用是什么?在什么情况下有用?
    java常用http请求库
  • 原文地址:https://www.cnblogs.com/rsapaper/p/9350094.html
Copyright © 2011-2022 走看看