• 关于

    python中d+

    的搜索结果

回答

详细解答可以参考官方帮助文档配置Logtail收集Python日志的详细操作步骤请参考Apache 日志,根据您的网络部署和实际情况选择对应配置。 在生成正则式的部分,由于自动生成的正则式只参考了日志样例,无法覆盖所有的日志情况,所以需要用户在自动生成之后做一些微调。 由于ThinkPHP是多行日志,而且模式并非固定,可以从日志中提取的字段包括时间、访问IP、访问的URL、以及打印的 Message。其中Message字段包含了多行信息,由于其模式不固定,只能打包到一个字段之中。 ThinkPHP日志的Logtail收集配置参数: 行首正则式 \[\s\d+-\d+-\w+:\d+:\d+\+\d+:\d+\s.* 正则表达式写成: \[\s(\d+-\d+-\w+:\d+:\d+)[^:]+:\d+\s]\s+(\S+)\s(\S+)\s+(.*) 时间表达式写成: %Y-%m-%dT%H:%M:%S

2019-12-01 23:12:02 0 浏览量 回答数 0

回答

熟记几个基本的命令行和使用方法能够较快的在Linux命令行环境中将python用起来。 打开命令行窗口 打开命令行窗口的快捷键如下: Ctrl + Alt + t 关闭名命令行窗口 关闭命令行窗口的快捷键如下: Ctrl + d 进入python环境 在命令行中直接输入python即进入了python的编辑环境。进入环境后最明显的提示是:光标由~$变成>>>。 退出python环境 使用ctrl +d的方式退出python环境。回到命令行环境。 在python环境中输入多行函数 在python环境中,回车是输入结束并执行语句。在输入多行函数的情况下,输入一行后回车则直接运行了某句代码而不是整个函数块。因此,需要能够换行但不结束输入的方法。 在语句的末尾输入英文的;即可实现换行。 例如: def weight_variable(shape): initial = tf.truncated_normal(shape, stddev=0.1);\ return tf.Variable(initial);\注意:输入函数块时注意缩进,否者会报出IndentationError: unexpected indent python错误。 输入中文字符导致non-ascii character xe5 in file解决方法 原因:程序中的编码错误,python默认支持acii模式,但不支持utf8,因此,程序中的中文注释会引发Error。 解决方法:源代码文件第一行添加#coding:utf-8即可避免。

世事皆空 2019-12-02 01:07:01 0 浏览量 回答数 0

回答

问题中发布的字节文字是有效的UTF-8。前两个字符是来自CJK统一表意文字块U + 683C和U + 6D74,U + 4E00 - U + 9FFF。由于您不知道源代码编码,因此无法完全确定它,但很可能电子邮件正文只是以UTF-8编码的汉字符(确定Python中文本的编码)。如果您无法正确查看UTF-8字符,则应检查终端或显示字符集。也就是说,你应该正确地获得角色表示的基础知识。随机编码或解码几乎无法解决任何问题。我建议你先阅读Spolsky对Unicode 的介绍,然后在Python中使用Unicode 转移到Batchelder。

一码平川MACHEL 2019-12-02 01:54:06 0 浏览量 回答数 0

万券齐发助力企业上云,爆款产品低至2.2折起!

限量神券最高减1000,抢完即止!云服务器ECS新用户首购低至0.95折!

问题

在PHP或NodeJS中实现Python编码代码

一码平川MACHEL 2019-12-01 19:31:19 660 浏览量 回答数 1

回答

Python 变量类型变量存储在内存中的值。这就意味着在创建变量时会在内存中开辟一个空间。基于变量的数据类型,解释器会分配指定内存,并决定什么数据可以被存储在内存中。因此,变量可以指定不同的数据类型,这些变量可以存储整数,小数或字符。 变量赋值Python 中的变量赋值不需要类型声明。每个变量在内存中创建,都包括变量的标识,名称和数据这些信息。每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建。等号(=)用来给变量赋值。等号(=)运算符左边是一个变量名,等号(=)运算符右边是存储在变量中的值。例如:实例(Python 2.0+) !/usr/bin/python -- coding: UTF-8 -- counter = 100 # 赋值整型变量miles = 1000.0 # 浮点型name = "John" # 字符串 print counterprint milesprint name 运行实例 »以上实例中,100,1000.0和"John"分别赋值给counter,miles,name变量。执行以上程序会输出如下结果:1001000.0John多个变量赋值Python允许你同时为多个变量赋值。例如:a = b = c = 1以上实例,创建一个整型对象,值为1,三个变量被分配到相同的内存空间上。您也可以为多个对象指定多个变量。例如:a, b, c = 1, 2, "john"以上实例,两个整型对象1和2的分配给变量 a 和 b,字符串对象 "john" 分配给变量 c。 标准数据类型在内存中存储的数据可以有多种类型。例如,一个人的年龄可以用数字来存储,他的名字可以用字符来存储。Python 定义了一些标准类型,用于存储各种类型的数据。Python有五个标准的数据类型:Numbers(数字)String(字符串)List(列表)Tuple(元组)Dictionary(字典) Python数字数字数据类型用于存储数值。他们是不可改变的数据类型,这意味着改变数字数据类型会分配一个新的对象。当你指定一个值时,Number对象就会被创建:var1 = 1var2 = 10您也可以使用del语句删除一些对象的引用。del语句的语法是:del var1[,var2[,var3[....,varN]]]]您可以通过使用del语句删除单个或多个对象的引用。例如:del vardel var_a, var_bPython支持四种不同的数字类型:int(有符号整型)long(长整型[也可以代表八进制和十六进制])float(浮点型)complex(复数)实例一些数值类型的实例:int long float complex10 51924361L 0.0 3.14j100 -0x19323L 15.20 45.j-786 0122L -21.9 9.322e-36j080 0xDEFABCECBDAECBFBAEl 32.3e+18 .876j-0490 535633629843L -90. -.6545+0J-0x260 -052318172735L -32.54e100 3e+26J0x69 -4721885298529L 70.2E-12 4.53e-7j长整型也可以使用小写 l,但是还是建议您使用大写 L,避免与数字 1 混淆。Python使用 L 来显示长整型。Python 还支持复数,复数由实数部分和虚数部分构成,可以用 a + bj,或者 complex(a,b) 表示, 复数的实部 a 和虚部 b 都是浮点型。 Python字符串字符串或串(String)是由数字、字母、下划线组成的一串字符。一般记为 :s="a1a2···an"(n>=0)它是编程语言中表示文本的数据类型。python的字串列表有2种取值顺序:从左到右索引默认0开始的,最大范围是字符串长度少1从右到左索引默认-1开始的,最大范围是字符串开头如果你要实现从字符串中获取一段子字符串的话,可以使用变量 [头下标:尾下标],就可以截取相应的字符串,其中下标是从 0 开始算起,可以是正数或负数,下标可以为空表示取到头或尾。比如:s = 'ilovepython's[1:5]的结果是love。当使用以冒号分隔的字符串,python返回一个新的对象,结果包含了以这对偏移标识的连续的内容,左边的开始是包含了下边界。上面的结果包含了s[1]的值l,而取到的最大范围不包括上边界,就是s[5]的值p。加号(+)是字符串连接运算符,星号(*)是重复操作。如下实例:实例(Python 2.0+) !/usr/bin/python -- coding: UTF-8 -- str = 'Hello World!' print str # 输出完整字符串print str[0] # 输出字符串中的第一个字符print str[2:5] # 输出字符串中第三个至第五个之间的字符串print str[2:] # 输出从第三个字符开始的字符串print str * 2 # 输出字符串两次print str + "TEST" # 输出连接的字符串以上实例输出结果:Hello World!Hllollo World!Hello World!Hello World!Hello World!TESTPython列表List(列表) 是 Python 中使用最频繁的数据类型。列表可以完成大多数集合类的数据结构实现。它支持字符,数字,字符串甚至可以包含列表(即嵌套)。列表用 [ ] 标识,是 python 最通用的复合数据类型。列表中值的切割也可以用到变量 [头下标:尾下标] ,就可以截取相应的列表,从左到右索引默认 0 开始,从右到左索引默认 -1 开始,下标可以为空表示取到头或尾。加号 + 是列表连接运算符,星号 * 是重复操作。如下实例:实例(Python 2.0+) !/usr/bin/python -- coding: UTF-8 -- list = [ 'runoob', 786 , 2.23, 'john', 70.2 ]tinylist = [123, 'john'] print list # 输出完整列表print list[0] # 输出列表的第一个元素print list[1:3] # 输出第二个至第三个元素 print list[2:] # 输出从第三个开始至列表末尾的所有元素print tinylist * 2 # 输出列表两次print list + tinylist # 打印组合的列表以上实例输出结果:['runoob', 786, 2.23, 'john', 70.2]runoob[786, 2.23][2.23, 'john', 70.2][123, 'john', 123, 'john']['runoob', 786, 2.23, 'john', 70.2, 123, 'john']Python元组元组是另一个数据类型,类似于List(列表)。元组用"()"标识。内部元素用逗号隔开。但是元组不能二次赋值,相当于只读列表。实例(Python 2.0+) !/usr/bin/python -- coding: UTF-8 -- tuple = ( 'runoob', 786 , 2.23, 'john', 70.2 )tinytuple = (123, 'john') print tuple # 输出完整元组print tuple[0] # 输出元组的第一个元素print tuple[1:3] # 输出第二个至第三个的元素 print tuple[2:] # 输出从第三个开始至列表末尾的所有元素print tinytuple * 2 # 输出元组两次print tuple + tinytuple # 打印组合的元组以上实例输出结果:('runoob', 786, 2.23, 'john', 70.2)runoob(786, 2.23)(2.23, 'john', 70.2)(123, 'john', 123, 'john')('runoob', 786, 2.23, 'john', 70.2, 123, 'john')以下是元组无效的,因为元组是不允许更新的。而列表是允许更新的:实例(Python 2.0+) !/usr/bin/python -- coding: UTF-8 -- tuple = ( 'runoob', 786 , 2.23, 'john', 70.2 )list = [ 'runoob', 786 , 2.23, 'john', 70.2 ]tuple[2] = 1000 # 元组中是非法应用list[2] = 1000 # 列表中是合法应用 Python 字典字典(dictionary)是除列表以外python之中最灵活的内置数据结构类型。列表是有序的对象集合,字典是无序的对象集合。两者之间的区别在于:字典当中的元素是通过键来存取的,而不是通过偏移存取。字典用"{ }"标识。字典由索引(key)和它对应的值value组成。实例(Python 2.0+) !/usr/bin/python -- coding: UTF-8 -- dict = {}dict['one'] = "This is one"dict[2] = "This is two" tinydict = {'name': 'john','code':6734, 'dept': 'sales'} print dict['one'] # 输出键为'one' 的值print dict[2] # 输出键为 2 的值print tinydict # 输出完整的字典print tinydict.keys() # 输出所有键print tinydict.values() # 输出所有值输出结果为:This is oneThis is two{'dept': 'sales', 'code': 6734, 'name': 'john'}['dept', 'code', 'name']['sales', 6734, 'john']Python数据类型转换有时候,我们需要对数据内置的类型进行转换,数据类型的转换,你只需要将数据类型作为函数名即可。以下几个内置的函数可以执行数据类型之间的转换。这些函数返回一个新的对象,表示转换的值。函数 描述int(x [,base])将x转换为一个整数long(x [,base] )将x转换为一个长整数float(x)将x转换到一个浮点数complex(real [,imag])创建一个复数str(x)将对象 x 转换为字符串repr(x)将对象 x 转换为表达式字符串eval(str)用来计算在字符串中的有效Python表达式,并返回一个对象tuple(s)将序列 s 转换为一个元组list(s)将序列 s 转换为一个列表set(s)转换为可变集合dict(d)创建一个字典。d 必须是一个序列 (key,value)元组。frozenset(s)转换为不可变集合chr(x)将一个整数转换为一个字符unichr(x)将一个整数转换为Unicode字符ord(x)将一个字符转换为它的整数值hex(x)将一个整数转换为一个十六进制字符串oct(x)将一个整数转换为一个八进制字符串

xuning715 2019-12-02 01:10:21 0 浏览量 回答数 0

回答

Python3 元组Python 的元组与列表类似,不同之处在于元组的元素不能修改。元组使用小括号,列表使用方括号。元组创建很简单,只需要在括号中添加元素,并使用逗号隔开即可。实例(Python 3.0+) tup1 = ('Google', 'Runoob', 1997, 2000);tup2 = (1, 2, 3, 4, 5 );tup3 = "a", "b", "c", "d"; # 不需要括号也可以type(tup3) 创建空元组tup1 = ();元组中只包含一个元素时,需要在元素后面添加逗号,否则括号会被当作运算符使用:实例(Python 3.0+) tup1 = (50)type(tup1) # 不加逗号,类型为整型 tup1 = (50,)type(tup1) # 加上逗号,类型为元组

世事皆空 2019-12-02 01:06:53 0 浏览量 回答数 0

回答

在同一个文件夹下 调用函数: A.py文件: [python] view plain copydef add(x,y): print('和为:%d'%(x+y)) B.py文件:[python] view plain copyimport A A.add(1,2) 或[python] view plain copyfrom A import add add(1,2) 调用类: A.py文件: [python] view plain copyclass A: def __init__(self,xx,yy): self.x=xx self.y=yy def add(self): print("x和y的和为:%d"%(self.x+self.y)) B.py文件:[python] view plain copyfrom A import A a=A(2,3) a.add() 或[python] view plain copyimport A a=A.A(2,3) a.add() 在不同文件夹下 A.py文件的文件路径:E:PythonProjectwinycg B.py文件:[python] view plain copyimport sys sys.path.append(r'E:PythonProjectwinycg') '''''python import模块时, 是在sys.path里按顺序查找的。 sys.path是一个列表,里面以字符串的形式存储了许多路径。 使用A.py文件中的函数需要先将他的文件路径放到sys.path中''' import A a=A.A(2,3) a.add()

xuning715 2019-12-02 01:10:15 0 浏览量 回答数 0

回答

//c语言多线程调python,必须加上红色字体,因为python本身不是线程安全的 PyObject* callPython(char* cpModelPath) { if(cpModelPath == NULL) return NULL; char modelPath[100] = ""; char modelName[21] = ""; int i; char* cp = cpModelPath; int len = strlen(cp); int len1 = len; if(len <= 0) { printf( "model is null, pid [%u] exit\n", (unsigned int)getpid() ); return; } while( *(cp + len - 1) != '/') { len--; } for(i = 0; i < len; ++i) modelPath[i] = *(cp+i); for(i = 0; i < len1-len; ++i) modelName[i] = *(cp+i+len); char modelPath1[100] = ""; strcpy(modelPath1, "sys.path.append('"); strcat(modelPath1, modelPath); strcat(modelPath1, "')"); PyRun_SimpleString("import sys"); PyRun_SimpleString(modelPath1); PyObject* pModule = NULL; PyObject* pDict = NULL; PyObject* pClass = NULL; PyObject* pObject = NULL; PyObject* pFunc = NULL; //调用python中的类 pModule = PyImport_ImportModule(modelName); if(!pModule) { printf( "model PyImport_ImportModule fail, pid [%u] thread [%u] exit\n", (unsigned int)getpid(), (unsigned int)pthread_self() ); return; } pDict = PyModule_GetDict(pModule); if(!pDict) { printf( "model PyModule_GetDict fail, pid [%u] thread [%u] exit\n", (unsigned int)getpid(), (unsigned int)pthread_self() ); return; } pClass = PyObject_GetAttrString(pModule, "JobNode");//得到那个类 if(!pClass || !PyCallable_Check(pClass)) { printf( "model PyObject_GetAttrString class fail, pid [%u] thread [%u] exit\n", (unsigned int)getpid(), (unsigned int)pthread_self() ); return; } pObject = PyEval_CallObject(pClass, NULL);//生成一个对象,或者叫作实例 pFunc = PyObject_GetAttrString(pObject, "createApp");//得到该实例的成员函数 if(!pFunc || !PyCallable_Check(pFunc)) { printf( "model PyObject_GetAttrString func fail, pid [%u] thread [%u] exit\n", (unsigned int)getpid(), (unsigned int)pthread_self() ); return; } Py_DECREF(pObject); Py_DECREF(pClass); Py_DECREF(pDict); Py_DECREF(pModule); return pFunc; } void* func(void* arg) { PyGILState_STATE gstate; gstate = PyGILState_Ensure(); PyObject* pFunc = NULL; PyObject* pArg = NULL; PyObject* pString = NULL; char* cpReturn; PyObject* p = callPython("/mnt/hgfs/D/emar_test/linux-test/marmoset/JobNode"); pFunc = p; pArg = PyTuple_New(1); // s 表示字符串, // i 表示整型变量, // f 表示浮点数, // O 表示一个Python对象。 PyTuple_SetItem(pArg, 0, Py_BuildValue("s", "Jacky")); pString = PyEval_CallObject(pFunc, pArg);//执行该实例的成员函数 cpReturn = PyString_AsString(pString); printf("cpReturn=%s\n",cpReturn); Py_DECREF(pString); Py_DECREF(pArg); Py_DECREF(pFunc); PyGILState_Release(gstate); } void main() { int num = 1; Py_Initialize(); if(!Py_IsInitialized()) { return; } PyEval_InitThreads(); PyEval_ReleaseThread(PyThreadState_Get()); pthread_t pid1,pid2; pthread_create(&pid1, NULL, func, NULL); pthread_create(&pid2, NULL, func, NULL); pthread_join(pid1, NULL); pthread_join(pid2, NULL); PyGILState_Ensure(); Py_Finalize();*/ }

a123456678 2019-12-02 02:45:10 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档 用户可以在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-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错误。 构建CanonicalizedOSSHeaders的方法 所有以 x-oss- 为前缀的HTTP Header被称为CanonicalizedOSSHeaders。它的构建方法如下: 将所有以 x-oss- 为前缀的HTTP请求头的名字转换成 小写 。如X-OSS-Meta-Name: TaoBao转换成x-oss-meta-name: TaoBao。 如果请求是以STS获得的AccessKeyId和AccessKeySecret发送时,还需要将获得的security-token值,以 x-oss-security-token:security-token 的形式加入到签名字符串中。 将上一步得到的所有HTTP请求头按照名字的字典序进行升序排列。 删除请求头和内容之间分隔符两端出现的任何空格。如x-oss-meta-name: TaoBao转换成:x-oss-meta-name:TaoBao。 将每一个头和内容用 \n 分隔符分隔拼成最后的CanonicalizedOSSHeaders。 说明 CanonicalizedOSSHeaders可以为空,无需添加最后的 \n。 如果只有一个,则如 x-oss-meta-a\n,注意最后的\n。 如果有多个,则如 x-oss-meta-a:a\nx-oss-meta-b:b\nx-oss-meta-c:c\n, 注意最后的\n。 构建CanonicalizedResource的方法 用户发送请求中想访问的OSS目标资源被称为CanonicalizedResource。它的构建方法如下: 将CanonicalizedResource置成空字符串 ""; 放入要访问的OSS资源 /BucketName/ObjectName(无ObjectName则CanonicalizedResource为”/BucketName/“,如果同时也没有BucketName则为“/”) 如果请求的资源包括子资源(SubResource) ,那么将所有的子资源按照字典序,从小到大排列并以 & 为分隔符生成子资源字符串。在CanonicalizedResource字符串尾添加 ?和子资源字符串。此时的CanonicalizedResource如:/BucketName/ObjectName?acl&uploadId=UploadId 如果用户请求在指定了查询字符串(QueryString,也叫Http Request Parameters),那么将这些查询字符串及其请求值按照 字典序,从小到大排列,以 & 为分隔符,按参数添加到CanonicalizedResource中。此时的CanonicalizedResource如:/BucketName/ObjectName?acl&response-content-type=ContentType&uploadId=UploadId。 说明 OSS目前支持的子资源(sub-resource)包括:acl,uploads,location,cors,logging,website,referer,lifecycle,delete,append,tagging,objectMeta,uploadId,partNumber,security-token,position,img,style,styleName,replication,replicationProgress,replicationLocation,cname,bucketInfo,comp,qos,live,status,vod,startTime,endTime,symlink,x-oss-process,response-content-type,response-content-language,response-expires,response-cache-control,response-content-disposition,response-content-encoding等 子资源(sub-resource)有三种类型: 资源标识,如子资源中的acl,append,uploadId,symlink等,详见关于Bucket的操作和关于Object的操作。 指定返回Header字段,如 response-***,详见GetObject的Request Parameters。 文件(Object)处理方式,如 x-oss-process,用于文件的处理方式,如图片处理。 计算签名头规则 签名的字符串必须为 UTF-8 格式。含有中文字符的签名字符串必须先进行 UTF-8 编码,再与 AccessKeySecret计算最终签名。 签名的方法用RFC 2104中定义的HMAC-SHA1方法,其中Key为 AccessKeySecret` 。 Content-Type 和 Content-MD5 在请求中不是必须的,但是如果请求需要签名验证,空值的话以换行符 \n 代替。 在所有非HTTP标准定义的header中,只有以 x-oss- 开头的header,需要加入签名字符串;其他非HTTP标准header将被OSS忽略(如上例中的x-oss-magic是需要加入签名字符串的)。 以 x-oss- 开头的header在签名验证前需要符合以下规范: header的名字需要变成小写。 header按字典序自小到大排序。 分割header name和value的冒号前后不能有空格。 每个Header之后都有一个换行符“\n”,如果没有Header,CanonicalizedOSSHeaders就设置为空。 签名示例 假如AccessKeyId是”44CF9590006BF252F707”,AccessKeySecret是”OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV” 请求 签名字符串计算公式 签名字符串 PUT /nelson HTTP/1.0 Content-MD5: eB5eJF1ptWaXm4bijSPyxw== Content-Type: text/html Date: Thu, 17 Nov 2005 18:49:58 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com X-OSS-Meta-Author: foo@bar.com X-OSS-Magic: abracadabra Signature = base64(hmac-sha1(AccessKeySecret,VERB + “\n” + Content-MD5 + “\n”+ Content-Type + “\n” + Date + “\n” + CanonicalizedOSSHeaders+ CanonicalizedResource)) “PUT\n eB5eJF1ptWaXm4bijSPyxw==\n text/html\n Thu, 17 Nov 2005 18:49:58 GMT\n x-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n/oss-example/nels 可用以下方法计算签名(Signature): python示例代码: import base64 import hmac import sha h = hmac.new("OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV", "PUT\nODBGOERFMDMzQTczRUY3NUE3NzA5QzdFNUYzMDQxNEM=\ntext/html\nThu, 17 Nov 2005 18:49:58 GMT\nx-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n/oss-example/nelson", sha) Signature = base64.b64encode(h.digest()) print("Signature: %s" % Signature) 签名(Signature)计算结果应该为 26NBxoKdsyly4EDv6inkoDft/yA=,因为Authorization = “OSS “ + AccessKeyId + “:” + Signature所以最后Authorization为 “OSS 44CF9590006BF252F707:26NBxoKdsyly4EDv6inkoDft/yA=”然后加上Authorization头来组成最后需要发送的消息: PUT /nelson HTTP/1.0 Authorization:OSS 44CF9590006BF252F707:26NBxoKdsyly4EDv6inkoDft/yA= Content-Md5: eB5eJF1ptWaXm4bijSPyxw== Content-Type: text/html Date: Thu, 17 Nov 2005 18:49:58 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com X-OSS-Meta-Author: foo@bar.com X-OSS-Magic: abracadabra 细节分析 如果传入的AccessKeyId不存在或inactive,返回403 Forbidden。错误码:InvalidAccessKeyId。 若用户请求头中Authorization值的格式不对,返回400 Bad Request。错误码:InvalidArgument。 OSS所有的请求都必须使用HTTP 1.1协议规定的GMT时间格式。其中,日期的格式为:date1 = 2DIGIT SP month SP 4DIGIT; day month year (e.g., 02 Jun 1982)上述日期格式中,“天”所占位数都是“2 DIGIT”。因此,“Jun 2”、“2 Jun 1982”和“2-Jun-82”都是非法日期格式。 如果签名验证的时候,头中没有传入Date或者格式不正确,返回403 Forbidden错误。错误码:AccessDenied。 传入请求的时间必须在OSS服务器当前时间之后的15分钟以内,否则返回403 Forbidden。错误码:RequestTimeTooSkewed。 如果AccessKeyId是active的,但OSS判断用户的请求发生签名错误,则返回403 Forbidden,并在返回给用户的response中告诉用户正确的用于验证加密的签名字符串。用户可以根据OSS的response来检查自己的签名字符串是否正确。返回示例:<?xml version="1.0" ?> <Error> <Code> SignatureDoesNotMatch </Code> <Message> The request signature we calculated does not match the signature you provided. Check your key and signing method. </Message> <StringToSignBytes> 47 45 54 0a 0a 0a 57 65 64 2c 20 31 31 20 4d 61 79 20 32 30 31 31 20 30 37 3a 35 39 3a 32 35 20 47 4d 54 0a 2f 75 73 72 65 61 6c 74 65 73 74 3f 61 63 6c </StringToSignBytes> <RequestId> 1E446260FF9B10C2 </RequestId> <HostId> oss-cn-hangzhou.aliyuncs.com </HostId> <SignatureProvided> y5H7yzPsA/tP4+0tH1HHvPEwUv8= </SignatureProvided> <StringToSign> GET Wed, 11 May 2011 07:59:25 GMT /oss-example?acl </StringToSign> <OSSAccessKeyId> AKIAIVAKMSMOY7VOMRWQ </OSSAccessKeyId> </Error> 说明 OSS SDK已经实现签名,用户使用OSS SDK不需要关注签名问题。如果您想了解具体语言的签名实现,请参考OSS SDK的代码。OSS SDK签名实现的文件如下表: SDK 签名实现 Java SDK OSSRequestSigner.java Python SDK auth.py .Net SDK OssRequestSigner.cs PHP SDK OssClient.php C SDK oss_auth.c JavaScript SDK client.js Go SDK auth.go Ruby SDK util.rb iOS SDK OSSModel.m Android SDK OSSUtils.java 当您自己实现签名,访问OSS报 SignatureDoesNotMatch 错误时,请使用可视化签名工具确认签名并排除错误。 常见问题 Content-MD5的计算方法 Content-MD5的计算 以消息内容为"123456789"来说,计算这个字符串的Content-MD5 正确的计算方式: 标准中定义的算法简单点说就是: 1. 先计算MD5加密的二进制数组(128位)。 2. 再对这个二进制进行base64编码(而不是对32位字符串编码)。 以Python为例子: 正确计算的代码为: >>> import base64,hashlib >>> hash = hashlib.md5() >>> hash.update("0123456789") >>> base64.b64encode(hash.digest()) 'eB5eJF1ptWaXm4bijSPyxw==' 需要注意 正确的是:hash.digest(),计算出进制数组(128位) >>> hash.digest() 'x\x1e^$]i\xb5f\x97\x9b\x86\xe2\x8d#\xf2\xc7' 常见错误是直接对计算出的32位字符串编码进行base64编码。 例如,错误的是:hash.hexdigest(),计算得到可见的32位字符串编码 >>> hash.hexdigest() '781e5e245d69b566979b86e28d23f2c7' 错误的MD5值进行base64编码后的结果: >>> base64.b64encode(hash.hexdigest()) 'NzgxZTVlMjQ1ZDY5YjU2Njk3OWI4NmUyOGQyM2YyYzc='

2019-12-01 23:13:44 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档 用户可以在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-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错误。 构建CanonicalizedOSSHeaders的方法 所有以 x-oss- 为前缀的HTTP Header被称为CanonicalizedOSSHeaders。它的构建方法如下: 将所有以 x-oss- 为前缀的HTTP请求头的名字转换成 小写 。如X-OSS-Meta-Name: TaoBao转换成x-oss-meta-name: TaoBao。 如果请求是以STS获得的AccessKeyId和AccessKeySecret发送时,还需要将获得的security-token值,以 x-oss-security-token:security-token 的形式加入到签名字符串中。 将上一步得到的所有HTTP请求头按照名字的字典序进行升序排列。 删除请求头和内容之间分隔符两端出现的任何空格。如x-oss-meta-name: TaoBao转换成:x-oss-meta-name:TaoBao。 将每一个头和内容用 \n 分隔符分隔拼成最后的CanonicalizedOSSHeaders。 说明 CanonicalizedOSSHeaders可以为空,无需添加最后的 \n。 如果只有一个,则如 x-oss-meta-a\n,注意最后的\n。 如果有多个,则如 x-oss-meta-a:a\nx-oss-meta-b:b\nx-oss-meta-c:c\n, 注意最后的\n。 构建CanonicalizedResource的方法 用户发送请求中想访问的OSS目标资源被称为CanonicalizedResource。它的构建方法如下: 将CanonicalizedResource置成空字符串 ""; 放入要访问的OSS资源 /BucketName/ObjectName(无ObjectName则CanonicalizedResource为”/BucketName/“,如果同时也没有BucketName则为“/”) 如果请求的资源包括子资源(SubResource) ,那么将所有的子资源按照字典序,从小到大排列并以 & 为分隔符生成子资源字符串。在CanonicalizedResource字符串尾添加 ?和子资源字符串。此时的CanonicalizedResource如:/BucketName/ObjectName?acl&uploadId=UploadId 如果用户请求在指定了查询字符串(QueryString,也叫Http Request Parameters),那么将这些查询字符串及其请求值按照 字典序,从小到大排列,以 & 为分隔符,按参数添加到CanonicalizedResource中。此时的CanonicalizedResource如:/BucketName/ObjectName?acl&response-content-type=ContentType&uploadId=UploadId。 说明 OSS目前支持的子资源(sub-resource)包括:acl,uploads,location,cors,logging,website,referer,lifecycle,delete,append,tagging,objectMeta,uploadId,partNumber,security-token,position,img,style,styleName,replication,replicationProgress,replicationLocation,cname,bucketInfo,comp,qos,live,status,vod,startTime,endTime,symlink,x-oss-process,response-content-type,response-content-language,response-expires,response-cache-control,response-content-disposition,response-content-encoding等 子资源(sub-resource)有三种类型: 资源标识,如子资源中的acl,append,uploadId,symlink等,详见关于Bucket的操作和关于Object的操作。 指定返回Header字段,如 response-***,详见GetObject的Request Parameters。 文件(Object)处理方式,如 x-oss-process,用于文件的处理方式,如图片处理。 计算签名头规则 签名的字符串必须为 UTF-8 格式。含有中文字符的签名字符串必须先进行 UTF-8 编码,再与 AccessKeySecret计算最终签名。 签名的方法用RFC 2104中定义的HMAC-SHA1方法,其中Key为 AccessKeySecret` 。 Content-Type 和 Content-MD5 在请求中不是必须的,但是如果请求需要签名验证,空值的话以换行符 \n 代替。 在所有非HTTP标准定义的header中,只有以 x-oss- 开头的header,需要加入签名字符串;其他非HTTP标准header将被OSS忽略(如上例中的x-oss-magic是需要加入签名字符串的)。 以 x-oss- 开头的header在签名验证前需要符合以下规范: header的名字需要变成小写。 header按字典序自小到大排序。 分割header name和value的冒号前后不能有空格。 每个Header之后都有一个换行符“\n”,如果没有Header,CanonicalizedOSSHeaders就设置为空。 签名示例 假如AccessKeyId是”44CF9590006BF252F707”,AccessKeySecret是”OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV” 请求 签名字符串计算公式 签名字符串 PUT /nelson HTTP/1.0 Content-MD5: eB5eJF1ptWaXm4bijSPyxw== Content-Type: text/html Date: Thu, 17 Nov 2005 18:49:58 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com X-OSS-Meta-Author: foo@bar.com X-OSS-Magic: abracadabra Signature = base64(hmac-sha1(AccessKeySecret,VERB + “\n” + Content-MD5 + “\n”+ Content-Type + “\n” + Date + “\n” + CanonicalizedOSSHeaders+ CanonicalizedResource)) “PUT\n eB5eJF1ptWaXm4bijSPyxw==\n text/html\n Thu, 17 Nov 2005 18:49:58 GMT\n x-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n/oss-example/nels 可用以下方法计算签名(Signature): python示例代码: import base64 import hmac import sha h = hmac.new("OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV", "PUT\nODBGOERFMDMzQTczRUY3NUE3NzA5QzdFNUYzMDQxNEM=\ntext/html\nThu, 17 Nov 2005 18:49:58 GMT\nx-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n/oss-example/nelson", sha) Signature = base64.b64encode(h.digest()) print("Signature: %s" % Signature) 签名(Signature)计算结果应该为 26NBxoKdsyly4EDv6inkoDft/yA=,因为Authorization = “OSS “ + AccessKeyId + “:” + Signature所以最后Authorization为 “OSS 44CF9590006BF252F707:26NBxoKdsyly4EDv6inkoDft/yA=”然后加上Authorization头来组成最后需要发送的消息: PUT /nelson HTTP/1.0 Authorization:OSS 44CF9590006BF252F707:26NBxoKdsyly4EDv6inkoDft/yA= Content-Md5: eB5eJF1ptWaXm4bijSPyxw== Content-Type: text/html Date: Thu, 17 Nov 2005 18:49:58 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com X-OSS-Meta-Author: foo@bar.com X-OSS-Magic: abracadabra 细节分析 如果传入的AccessKeyId不存在或inactive,返回403 Forbidden。错误码:InvalidAccessKeyId。 若用户请求头中Authorization值的格式不对,返回400 Bad Request。错误码:InvalidArgument。 OSS所有的请求都必须使用HTTP 1.1协议规定的GMT时间格式。其中,日期的格式为:date1 = 2DIGIT SP month SP 4DIGIT; day month year (e.g., 02 Jun 1982)上述日期格式中,“天”所占位数都是“2 DIGIT”。因此,“Jun 2”、“2 Jun 1982”和“2-Jun-82”都是非法日期格式。 如果签名验证的时候,头中没有传入Date或者格式不正确,返回403 Forbidden错误。错误码:AccessDenied。 传入请求的时间必须在OSS服务器当前时间之后的15分钟以内,否则返回403 Forbidden。错误码:RequestTimeTooSkewed。 如果AccessKeyId是active的,但OSS判断用户的请求发生签名错误,则返回403 Forbidden,并在返回给用户的response中告诉用户正确的用于验证加密的签名字符串。用户可以根据OSS的response来检查自己的签名字符串是否正确。返回示例:<?xml version="1.0" ?> <Error> <Code> SignatureDoesNotMatch </Code> <Message> The request signature we calculated does not match the signature you provided. Check your key and signing method. </Message> <StringToSignBytes> 47 45 54 0a 0a 0a 57 65 64 2c 20 31 31 20 4d 61 79 20 32 30 31 31 20 30 37 3a 35 39 3a 32 35 20 47 4d 54 0a 2f 75 73 72 65 61 6c 74 65 73 74 3f 61 63 6c </StringToSignBytes> <RequestId> 1E446260FF9B10C2 </RequestId> <HostId> oss-cn-hangzhou.aliyuncs.com </HostId> <SignatureProvided> y5H7yzPsA/tP4+0tH1HHvPEwUv8= </SignatureProvided> <StringToSign> GET Wed, 11 May 2011 07:59:25 GMT /oss-example?acl </StringToSign> <OSSAccessKeyId> AKIAIVAKMSMOY7VOMRWQ </OSSAccessKeyId> </Error> 说明 OSS SDK已经实现签名,用户使用OSS SDK不需要关注签名问题。如果您想了解具体语言的签名实现,请参考OSS SDK的代码。OSS SDK签名实现的文件如下表: SDK 签名实现 Java SDK OSSRequestSigner.java Python SDK auth.py .Net SDK OssRequestSigner.cs PHP SDK OssClient.php C SDK oss_auth.c JavaScript SDK client.js Go SDK auth.go Ruby SDK util.rb iOS SDK OSSModel.m Android SDK OSSUtils.java 当您自己实现签名,访问OSS报 SignatureDoesNotMatch 错误时,请使用可视化签名工具确认签名并排除错误。 常见问题 Content-MD5的计算方法 Content-MD5的计算 以消息内容为"123456789"来说,计算这个字符串的Content-MD5 正确的计算方式: 标准中定义的算法简单点说就是: 1. 先计算MD5加密的二进制数组(128位)。 2. 再对这个二进制进行base64编码(而不是对32位字符串编码)。 以Python为例子: 正确计算的代码为: >>> import base64,hashlib >>> hash = hashlib.md5() >>> hash.update("0123456789") >>> base64.b64encode(hash.digest()) 'eB5eJF1ptWaXm4bijSPyxw==' 需要注意 正确的是:hash.digest(),计算出进制数组(128位) >>> hash.digest() 'x\x1e^$]i\xb5f\x97\x9b\x86\xe2\x8d#\xf2\xc7' 常见错误是直接对计算出的32位字符串编码进行base64编码。 例如,错误的是:hash.hexdigest(),计算得到可见的32位字符串编码 >>> hash.hexdigest() '781e5e245d69b566979b86e28d23f2c7' 错误的MD5值进行base64编码后的结果: >>> base64.b64encode(hash.hexdigest()) 'NzgxZTVlMjQ1ZDY5YjU2Njk3OWI4NmUyOGQyM2YyYzc='

2019-12-01 23:13:44 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档 用户可以在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-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错误。 构建CanonicalizedOSSHeaders的方法 所有以 x-oss- 为前缀的HTTP Header被称为CanonicalizedOSSHeaders。它的构建方法如下: 将所有以 x-oss- 为前缀的HTTP请求头的名字转换成 小写 。如X-OSS-Meta-Name: TaoBao转换成x-oss-meta-name: TaoBao。 如果请求是以STS获得的AccessKeyId和AccessKeySecret发送时,还需要将获得的security-token值,以 x-oss-security-token:security-token 的形式加入到签名字符串中。 将上一步得到的所有HTTP请求头按照名字的字典序进行升序排列。 删除请求头和内容之间分隔符两端出现的任何空格。如x-oss-meta-name: TaoBao转换成:x-oss-meta-name:TaoBao。 将每一个头和内容用 \n 分隔符分隔拼成最后的CanonicalizedOSSHeaders。 说明 CanonicalizedOSSHeaders可以为空,无需添加最后的 \n。 如果只有一个,则如 x-oss-meta-a\n,注意最后的\n。 如果有多个,则如 x-oss-meta-a:a\nx-oss-meta-b:b\nx-oss-meta-c:c\n, 注意最后的\n。 构建CanonicalizedResource的方法 用户发送请求中想访问的OSS目标资源被称为CanonicalizedResource。它的构建方法如下: 将CanonicalizedResource置成空字符串 ""; 放入要访问的OSS资源 /BucketName/ObjectName(无ObjectName则CanonicalizedResource为”/BucketName/“,如果同时也没有BucketName则为“/”) 如果请求的资源包括子资源(SubResource) ,那么将所有的子资源按照字典序,从小到大排列并以 & 为分隔符生成子资源字符串。在CanonicalizedResource字符串尾添加 ?和子资源字符串。此时的CanonicalizedResource如:/BucketName/ObjectName?acl&uploadId=UploadId 如果用户请求在指定了查询字符串(QueryString,也叫Http Request Parameters),那么将这些查询字符串及其请求值按照 字典序,从小到大排列,以 & 为分隔符,按参数添加到CanonicalizedResource中。此时的CanonicalizedResource如:/BucketName/ObjectName?acl&response-content-type=ContentType&uploadId=UploadId。 说明 OSS目前支持的子资源(sub-resource)包括:acl,uploads,location,cors,logging,website,referer,lifecycle,delete,append,tagging,objectMeta,uploadId,partNumber,security-token,position,img,style,styleName,replication,replicationProgress,replicationLocation,cname,bucketInfo,comp,qos,live,status,vod,startTime,endTime,symlink,x-oss-process,response-content-type,response-content-language,response-expires,response-cache-control,response-content-disposition,response-content-encoding等 子资源(sub-resource)有三种类型: 资源标识,如子资源中的acl,append,uploadId,symlink等,详见关于Bucket的操作和关于Object的操作。 指定返回Header字段,如 response-***,详见GetObject的Request Parameters。 文件(Object)处理方式,如 x-oss-process,用于文件的处理方式,如图片处理。 计算签名头规则 签名的字符串必须为 UTF-8 格式。含有中文字符的签名字符串必须先进行 UTF-8 编码,再与 AccessKeySecret计算最终签名。 签名的方法用RFC 2104中定义的HMAC-SHA1方法,其中Key为 AccessKeySecret` 。 Content-Type 和 Content-MD5 在请求中不是必须的,但是如果请求需要签名验证,空值的话以换行符 \n 代替。 在所有非HTTP标准定义的header中,只有以 x-oss- 开头的header,需要加入签名字符串;其他非HTTP标准header将被OSS忽略(如上例中的x-oss-magic是需要加入签名字符串的)。 以 x-oss- 开头的header在签名验证前需要符合以下规范: header的名字需要变成小写。 header按字典序自小到大排序。 分割header name和value的冒号前后不能有空格。 每个Header之后都有一个换行符“\n”,如果没有Header,CanonicalizedOSSHeaders就设置为空。 签名示例 假如AccessKeyId是”44CF9590006BF252F707”,AccessKeySecret是”OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV” 请求 签名字符串计算公式 签名字符串 PUT /nelson HTTP/1.0 Content-MD5: eB5eJF1ptWaXm4bijSPyxw== Content-Type: text/html Date: Thu, 17 Nov 2005 18:49:58 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com X-OSS-Meta-Author: foo@bar.com X-OSS-Magic: abracadabra Signature = base64(hmac-sha1(AccessKeySecret,VERB + “\n” + Content-MD5 + “\n”+ Content-Type + “\n” + Date + “\n” + CanonicalizedOSSHeaders+ CanonicalizedResource)) “PUT\n eB5eJF1ptWaXm4bijSPyxw==\n text/html\n Thu, 17 Nov 2005 18:49:58 GMT\n x-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n/oss-example/nels 可用以下方法计算签名(Signature): python示例代码: import base64 import hmac import sha h = hmac.new("OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV", "PUT\nODBGOERFMDMzQTczRUY3NUE3NzA5QzdFNUYzMDQxNEM=\ntext/html\nThu, 17 Nov 2005 18:49:58 GMT\nx-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n/oss-example/nelson", sha) Signature = base64.b64encode(h.digest()) print("Signature: %s" % Signature) 签名(Signature)计算结果应该为 26NBxoKdsyly4EDv6inkoDft/yA=,因为Authorization = “OSS “ + AccessKeyId + “:” + Signature所以最后Authorization为 “OSS 44CF9590006BF252F707:26NBxoKdsyly4EDv6inkoDft/yA=”然后加上Authorization头来组成最后需要发送的消息: PUT /nelson HTTP/1.0 Authorization:OSS 44CF9590006BF252F707:26NBxoKdsyly4EDv6inkoDft/yA= Content-Md5: eB5eJF1ptWaXm4bijSPyxw== Content-Type: text/html Date: Thu, 17 Nov 2005 18:49:58 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com X-OSS-Meta-Author: foo@bar.com X-OSS-Magic: abracadabra 细节分析 如果传入的AccessKeyId不存在或inactive,返回403 Forbidden。错误码:InvalidAccessKeyId。 若用户请求头中Authorization值的格式不对,返回400 Bad Request。错误码:InvalidArgument。 OSS所有的请求都必须使用HTTP 1.1协议规定的GMT时间格式。其中,日期的格式为:date1 = 2DIGIT SP month SP 4DIGIT; day month year (e.g., 02 Jun 1982)上述日期格式中,“天”所占位数都是“2 DIGIT”。因此,“Jun 2”、“2 Jun 1982”和“2-Jun-82”都是非法日期格式。 如果签名验证的时候,头中没有传入Date或者格式不正确,返回403 Forbidden错误。错误码:AccessDenied。 传入请求的时间必须在OSS服务器当前时间之后的15分钟以内,否则返回403 Forbidden。错误码:RequestTimeTooSkewed。 如果AccessKeyId是active的,但OSS判断用户的请求发生签名错误,则返回403 Forbidden,并在返回给用户的response中告诉用户正确的用于验证加密的签名字符串。用户可以根据OSS的response来检查自己的签名字符串是否正确。返回示例:<?xml version="1.0" ?> <Error> <Code> SignatureDoesNotMatch </Code> <Message> The request signature we calculated does not match the signature you provided. Check your key and signing method. </Message> <StringToSignBytes> 47 45 54 0a 0a 0a 57 65 64 2c 20 31 31 20 4d 61 79 20 32 30 31 31 20 30 37 3a 35 39 3a 32 35 20 47 4d 54 0a 2f 75 73 72 65 61 6c 74 65 73 74 3f 61 63 6c </StringToSignBytes> <RequestId> 1E446260FF9B10C2 </RequestId> <HostId> oss-cn-hangzhou.aliyuncs.com </HostId> <SignatureProvided> y5H7yzPsA/tP4+0tH1HHvPEwUv8= </SignatureProvided> <StringToSign> GET Wed, 11 May 2011 07:59:25 GMT /oss-example?acl </StringToSign> <OSSAccessKeyId> AKIAIVAKMSMOY7VOMRWQ </OSSAccessKeyId> </Error> 说明 OSS SDK已经实现签名,用户使用OSS SDK不需要关注签名问题。如果您想了解具体语言的签名实现,请参考OSS SDK的代码。OSS SDK签名实现的文件如下表: SDK 签名实现 Java SDK OSSRequestSigner.java Python SDK auth.py .Net SDK OssRequestSigner.cs PHP SDK OssClient.php C SDK oss_auth.c JavaScript SDK client.js Go SDK auth.go Ruby SDK util.rb iOS SDK OSSModel.m Android SDK OSSUtils.java 当您自己实现签名,访问OSS报 SignatureDoesNotMatch 错误时,请使用可视化签名工具确认签名并排除错误。 常见问题 Content-MD5的计算方法 Content-MD5的计算 以消息内容为"123456789"来说,计算这个字符串的Content-MD5 正确的计算方式: 标准中定义的算法简单点说就是: 1. 先计算MD5加密的二进制数组(128位)。 2. 再对这个二进制进行base64编码(而不是对32位字符串编码)。 以Python为例子: 正确计算的代码为: >>> import base64,hashlib >>> hash = hashlib.md5() >>> hash.update("0123456789") >>> base64.b64encode(hash.digest()) 'eB5eJF1ptWaXm4bijSPyxw==' 需要注意 正确的是:hash.digest(),计算出进制数组(128位) >>> hash.digest() 'x\x1e^$]i\xb5f\x97\x9b\x86\xe2\x8d#\xf2\xc7' 常见错误是直接对计算出的32位字符串编码进行base64编码。 例如,错误的是:hash.hexdigest(),计算得到可见的32位字符串编码 >>> hash.hexdigest() '781e5e245d69b566979b86e28d23f2c7' 错误的MD5值进行base64编码后的结果: >>> base64.b64encode(hash.hexdigest()) 'NzgxZTVlMjQ1ZDY5YjU2Njk3OWI4NmUyOGQyM2YyYzc='

2019-12-01 23:13:45 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档 用户可以在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-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错误。 构建CanonicalizedOSSHeaders的方法 所有以 x-oss- 为前缀的HTTP Header被称为CanonicalizedOSSHeaders。它的构建方法如下: 将所有以 x-oss- 为前缀的HTTP请求头的名字转换成 小写 。如X-OSS-Meta-Name: TaoBao转换成x-oss-meta-name: TaoBao。 如果请求是以STS获得的AccessKeyId和AccessKeySecret发送时,还需要将获得的security-token值,以 x-oss-security-token:security-token 的形式加入到签名字符串中。 将上一步得到的所有HTTP请求头按照名字的字典序进行升序排列。 删除请求头和内容之间分隔符两端出现的任何空格。如x-oss-meta-name: TaoBao转换成:x-oss-meta-name:TaoBao。 将每一个头和内容用 \n 分隔符分隔拼成最后的CanonicalizedOSSHeaders。 说明 CanonicalizedOSSHeaders可以为空,无需添加最后的 \n。 如果只有一个,则如 x-oss-meta-a\n,注意最后的\n。 如果有多个,则如 x-oss-meta-a:a\nx-oss-meta-b:b\nx-oss-meta-c:c\n, 注意最后的\n。 构建CanonicalizedResource的方法 用户发送请求中想访问的OSS目标资源被称为CanonicalizedResource。它的构建方法如下: 将CanonicalizedResource置成空字符串 ""; 放入要访问的OSS资源 /BucketName/ObjectName(无ObjectName则CanonicalizedResource为”/BucketName/“,如果同时也没有BucketName则为“/”) 如果请求的资源包括子资源(SubResource) ,那么将所有的子资源按照字典序,从小到大排列并以 & 为分隔符生成子资源字符串。在CanonicalizedResource字符串尾添加 ?和子资源字符串。此时的CanonicalizedResource如:/BucketName/ObjectName?acl&uploadId=UploadId 如果用户请求在指定了查询字符串(QueryString,也叫Http Request Parameters),那么将这些查询字符串及其请求值按照 字典序,从小到大排列,以 & 为分隔符,按参数添加到CanonicalizedResource中。此时的CanonicalizedResource如:/BucketName/ObjectName?acl&response-content-type=ContentType&uploadId=UploadId。 说明 OSS目前支持的子资源(sub-resource)包括:acl,uploads,location,cors,logging,website,referer,lifecycle,delete,append,tagging,objectMeta,uploadId,partNumber,security-token,position,img,style,styleName,replication,replicationProgress,replicationLocation,cname,bucketInfo,comp,qos,live,status,vod,startTime,endTime,symlink,x-oss-process,response-content-type,response-content-language,response-expires,response-cache-control,response-content-disposition,response-content-encoding等 子资源(sub-resource)有三种类型: 资源标识,如子资源中的acl,append,uploadId,symlink等,详见关于Bucket的操作和关于Object的操作。 指定返回Header字段,如 response-***,详见GetObject的Request Parameters。 文件(Object)处理方式,如 x-oss-process,用于文件的处理方式,如图片处理。 计算签名头规则 签名的字符串必须为 UTF-8 格式。含有中文字符的签名字符串必须先进行 UTF-8 编码,再与 AccessKeySecret计算最终签名。 签名的方法用RFC 2104中定义的HMAC-SHA1方法,其中Key为 AccessKeySecret` 。 Content-Type 和 Content-MD5 在请求中不是必须的,但是如果请求需要签名验证,空值的话以换行符 \n 代替。 在所有非HTTP标准定义的header中,只有以 x-oss- 开头的header,需要加入签名字符串;其他非HTTP标准header将被OSS忽略(如上例中的x-oss-magic是需要加入签名字符串的)。 以 x-oss- 开头的header在签名验证前需要符合以下规范: header的名字需要变成小写。 header按字典序自小到大排序。 分割header name和value的冒号前后不能有空格。 每个Header之后都有一个换行符“\n”,如果没有Header,CanonicalizedOSSHeaders就设置为空。 签名示例 假如AccessKeyId是”44CF9590006BF252F707”,AccessKeySecret是”OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV” 请求 签名字符串计算公式 签名字符串 PUT /nelson HTTP/1.0 Content-MD5: eB5eJF1ptWaXm4bijSPyxw== Content-Type: text/html Date: Thu, 17 Nov 2005 18:49:58 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com X-OSS-Meta-Author: foo@bar.com X-OSS-Magic: abracadabra Signature = base64(hmac-sha1(AccessKeySecret,VERB + “\n” + Content-MD5 + “\n”+ Content-Type + “\n” + Date + “\n” + CanonicalizedOSSHeaders+ CanonicalizedResource)) “PUT\n eB5eJF1ptWaXm4bijSPyxw==\n text/html\n Thu, 17 Nov 2005 18:49:58 GMT\n x-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n/oss-example/nels 可用以下方法计算签名(Signature): python示例代码: import base64 import hmac import sha h = hmac.new("OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV", "PUT\nODBGOERFMDMzQTczRUY3NUE3NzA5QzdFNUYzMDQxNEM=\ntext/html\nThu, 17 Nov 2005 18:49:58 GMT\nx-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n/oss-example/nelson", sha) Signature = base64.b64encode(h.digest()) print("Signature: %s" % Signature) 签名(Signature)计算结果应该为 26NBxoKdsyly4EDv6inkoDft/yA=,因为Authorization = “OSS “ + AccessKeyId + “:” + Signature所以最后Authorization为 “OSS 44CF9590006BF252F707:26NBxoKdsyly4EDv6inkoDft/yA=”然后加上Authorization头来组成最后需要发送的消息: PUT /nelson HTTP/1.0 Authorization:OSS 44CF9590006BF252F707:26NBxoKdsyly4EDv6inkoDft/yA= Content-Md5: eB5eJF1ptWaXm4bijSPyxw== Content-Type: text/html Date: Thu, 17 Nov 2005 18:49:58 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com X-OSS-Meta-Author: foo@bar.com X-OSS-Magic: abracadabra 细节分析 如果传入的AccessKeyId不存在或inactive,返回403 Forbidden。错误码:InvalidAccessKeyId。 若用户请求头中Authorization值的格式不对,返回400 Bad Request。错误码:InvalidArgument。 OSS所有的请求都必须使用HTTP 1.1协议规定的GMT时间格式。其中,日期的格式为:date1 = 2DIGIT SP month SP 4DIGIT; day month year (e.g., 02 Jun 1982)上述日期格式中,“天”所占位数都是“2 DIGIT”。因此,“Jun 2”、“2 Jun 1982”和“2-Jun-82”都是非法日期格式。 如果签名验证的时候,头中没有传入Date或者格式不正确,返回403 Forbidden错误。错误码:AccessDenied。 传入请求的时间必须在OSS服务器当前时间之后的15分钟以内,否则返回403 Forbidden。错误码:RequestTimeTooSkewed。 如果AccessKeyId是active的,但OSS判断用户的请求发生签名错误,则返回403 Forbidden,并在返回给用户的response中告诉用户正确的用于验证加密的签名字符串。用户可以根据OSS的response来检查自己的签名字符串是否正确。返回示例:<?xml version="1.0" ?> <Error> <Code> SignatureDoesNotMatch </Code> <Message> The request signature we calculated does not match the signature you provided. Check your key and signing method. </Message> <StringToSignBytes> 47 45 54 0a 0a 0a 57 65 64 2c 20 31 31 20 4d 61 79 20 32 30 31 31 20 30 37 3a 35 39 3a 32 35 20 47 4d 54 0a 2f 75 73 72 65 61 6c 74 65 73 74 3f 61 63 6c </StringToSignBytes> <RequestId> 1E446260FF9B10C2 </RequestId> <HostId> oss-cn-hangzhou.aliyuncs.com </HostId> <SignatureProvided> y5H7yzPsA/tP4+0tH1HHvPEwUv8= </SignatureProvided> <StringToSign> GET Wed, 11 May 2011 07:59:25 GMT /oss-example?acl </StringToSign> <OSSAccessKeyId> AKIAIVAKMSMOY7VOMRWQ </OSSAccessKeyId> </Error> 说明 OSS SDK已经实现签名,用户使用OSS SDK不需要关注签名问题。如果您想了解具体语言的签名实现,请参考OSS SDK的代码。OSS SDK签名实现的文件如下表: SDK 签名实现 Java SDK OSSRequestSigner.java Python SDK auth.py .Net SDK OssRequestSigner.cs PHP SDK OssClient.php C SDK oss_auth.c JavaScript SDK client.js Go SDK auth.go Ruby SDK util.rb iOS SDK OSSModel.m Android SDK OSSUtils.java 当您自己实现签名,访问OSS报 SignatureDoesNotMatch 错误时,请使用可视化签名工具确认签名并排除错误。 常见问题 Content-MD5的计算方法 Content-MD5的计算 以消息内容为"123456789"来说,计算这个字符串的Content-MD5 正确的计算方式: 标准中定义的算法简单点说就是: 1. 先计算MD5加密的二进制数组(128位)。 2. 再对这个二进制进行base64编码(而不是对32位字符串编码)。 以Python为例子: 正确计算的代码为: >>> import base64,hashlib >>> hash = hashlib.md5() >>> hash.update("0123456789") >>> base64.b64encode(hash.digest()) 'eB5eJF1ptWaXm4bijSPyxw==' 需要注意 正确的是:hash.digest(),计算出进制数组(128位) >>> hash.digest() 'x\x1e^$]i\xb5f\x97\x9b\x86\xe2\x8d#\xf2\xc7' 常见错误是直接对计算出的32位字符串编码进行base64编码。 例如,错误的是:hash.hexdigest(),计算得到可见的32位字符串编码 >>> hash.hexdigest() '781e5e245d69b566979b86e28d23f2c7' 错误的MD5值进行base64编码后的结果: >>> base64.b64encode(hash.hexdigest()) 'NzgxZTVlMjQ1ZDY5YjU2Njk3OWI4NmUyOGQyM2YyYzc='

2019-12-01 23:13:45 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档 用户可以在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-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错误。 构建CanonicalizedOSSHeaders的方法 所有以 x-oss- 为前缀的HTTP Header被称为CanonicalizedOSSHeaders。它的构建方法如下: 将所有以 x-oss- 为前缀的HTTP请求头的名字转换成 小写 。如X-OSS-Meta-Name: TaoBao转换成x-oss-meta-name: TaoBao。 如果请求是以STS获得的AccessKeyId和AccessKeySecret发送时,还需要将获得的security-token值,以 x-oss-security-token:security-token 的形式加入到签名字符串中。 将上一步得到的所有HTTP请求头按照名字的字典序进行升序排列。 删除请求头和内容之间分隔符两端出现的任何空格。如x-oss-meta-name: TaoBao转换成:x-oss-meta-name:TaoBao。 将每一个头和内容用 \n 分隔符分隔拼成最后的CanonicalizedOSSHeaders。 说明 CanonicalizedOSSHeaders可以为空,无需添加最后的 \n。 如果只有一个,则如 x-oss-meta-a\n,注意最后的\n。 如果有多个,则如 x-oss-meta-a:a\nx-oss-meta-b:b\nx-oss-meta-c:c\n, 注意最后的\n。 构建CanonicalizedResource的方法 用户发送请求中想访问的OSS目标资源被称为CanonicalizedResource。它的构建方法如下: 将CanonicalizedResource置成空字符串 ""; 放入要访问的OSS资源 /BucketName/ObjectName(无ObjectName则CanonicalizedResource为”/BucketName/“,如果同时也没有BucketName则为“/”) 如果请求的资源包括子资源(SubResource) ,那么将所有的子资源按照字典序,从小到大排列并以 & 为分隔符生成子资源字符串。在CanonicalizedResource字符串尾添加 ?和子资源字符串。此时的CanonicalizedResource如:/BucketName/ObjectName?acl&uploadId=UploadId 如果用户请求在指定了查询字符串(QueryString,也叫Http Request Parameters),那么将这些查询字符串及其请求值按照 字典序,从小到大排列,以 & 为分隔符,按参数添加到CanonicalizedResource中。此时的CanonicalizedResource如:/BucketName/ObjectName?acl&response-content-type=ContentType&uploadId=UploadId。 说明 OSS目前支持的子资源(sub-resource)包括:acl,uploads,location,cors,logging,website,referer,lifecycle,delete,append,tagging,objectMeta,uploadId,partNumber,security-token,position,img,style,styleName,replication,replicationProgress,replicationLocation,cname,bucketInfo,comp,qos,live,status,vod,startTime,endTime,symlink,x-oss-process,response-content-type,response-content-language,response-expires,response-cache-control,response-content-disposition,response-content-encoding等 子资源(sub-resource)有三种类型: 资源标识,如子资源中的acl,append,uploadId,symlink等,详见关于Bucket的操作和关于Object的操作。 指定返回Header字段,如 response-***,详见GetObject的Request Parameters。 文件(Object)处理方式,如 x-oss-process,用于文件的处理方式,如图片处理。 计算签名头规则 签名的字符串必须为 UTF-8 格式。含有中文字符的签名字符串必须先进行 UTF-8 编码,再与 AccessKeySecret计算最终签名。 签名的方法用RFC 2104中定义的HMAC-SHA1方法,其中Key为 AccessKeySecret` 。 Content-Type 和 Content-MD5 在请求中不是必须的,但是如果请求需要签名验证,空值的话以换行符 \n 代替。 在所有非HTTP标准定义的header中,只有以 x-oss- 开头的header,需要加入签名字符串;其他非HTTP标准header将被OSS忽略(如上例中的x-oss-magic是需要加入签名字符串的)。 以 x-oss- 开头的header在签名验证前需要符合以下规范: header的名字需要变成小写。 header按字典序自小到大排序。 分割header name和value的冒号前后不能有空格。 每个Header之后都有一个换行符“\n”,如果没有Header,CanonicalizedOSSHeaders就设置为空。 签名示例 假如AccessKeyId是”44CF9590006BF252F707”,AccessKeySecret是”OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV” 请求 签名字符串计算公式 签名字符串 PUT /nelson HTTP/1.0 Content-MD5: eB5eJF1ptWaXm4bijSPyxw== Content-Type: text/html Date: Thu, 17 Nov 2005 18:49:58 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com X-OSS-Meta-Author: foo@bar.com X-OSS-Magic: abracadabra Signature = base64(hmac-sha1(AccessKeySecret,VERB + “\n” + Content-MD5 + “\n”+ Content-Type + “\n” + Date + “\n” + CanonicalizedOSSHeaders+ CanonicalizedResource)) “PUT\n eB5eJF1ptWaXm4bijSPyxw==\n text/html\n Thu, 17 Nov 2005 18:49:58 GMT\n x-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n/oss-example/nels 可用以下方法计算签名(Signature): python示例代码: import base64 import hmac import sha h = hmac.new("OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV", "PUT\nODBGOERFMDMzQTczRUY3NUE3NzA5QzdFNUYzMDQxNEM=\ntext/html\nThu, 17 Nov 2005 18:49:58 GMT\nx-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n/oss-example/nelson", sha) Signature = base64.b64encode(h.digest()) print("Signature: %s" % Signature) 签名(Signature)计算结果应该为 26NBxoKdsyly4EDv6inkoDft/yA=,因为Authorization = “OSS “ + AccessKeyId + “:” + Signature所以最后Authorization为 “OSS 44CF9590006BF252F707:26NBxoKdsyly4EDv6inkoDft/yA=”然后加上Authorization头来组成最后需要发送的消息: PUT /nelson HTTP/1.0 Authorization:OSS 44CF9590006BF252F707:26NBxoKdsyly4EDv6inkoDft/yA= Content-Md5: eB5eJF1ptWaXm4bijSPyxw== Content-Type: text/html Date: Thu, 17 Nov 2005 18:49:58 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com X-OSS-Meta-Author: foo@bar.com X-OSS-Magic: abracadabra 细节分析 如果传入的AccessKeyId不存在或inactive,返回403 Forbidden。错误码:InvalidAccessKeyId。 若用户请求头中Authorization值的格式不对,返回400 Bad Request。错误码:InvalidArgument。 OSS所有的请求都必须使用HTTP 1.1协议规定的GMT时间格式。其中,日期的格式为:date1 = 2DIGIT SP month SP 4DIGIT; day month year (e.g., 02 Jun 1982)上述日期格式中,“天”所占位数都是“2 DIGIT”。因此,“Jun 2”、“2 Jun 1982”和“2-Jun-82”都是非法日期格式。 如果签名验证的时候,头中没有传入Date或者格式不正确,返回403 Forbidden错误。错误码:AccessDenied。 传入请求的时间必须在OSS服务器当前时间之后的15分钟以内,否则返回403 Forbidden。错误码:RequestTimeTooSkewed。 如果AccessKeyId是active的,但OSS判断用户的请求发生签名错误,则返回403 Forbidden,并在返回给用户的response中告诉用户正确的用于验证加密的签名字符串。用户可以根据OSS的response来检查自己的签名字符串是否正确。返回示例:<?xml version="1.0" ?> <Error> <Code> SignatureDoesNotMatch </Code> <Message> The request signature we calculated does not match the signature you provided. Check your key and signing method. </Message> <StringToSignBytes> 47 45 54 0a 0a 0a 57 65 64 2c 20 31 31 20 4d 61 79 20 32 30 31 31 20 30 37 3a 35 39 3a 32 35 20 47 4d 54 0a 2f 75 73 72 65 61 6c 74 65 73 74 3f 61 63 6c </StringToSignBytes> <RequestId> 1E446260FF9B10C2 </RequestId> <HostId> oss-cn-hangzhou.aliyuncs.com </HostId> <SignatureProvided> y5H7yzPsA/tP4+0tH1HHvPEwUv8= </SignatureProvided> <StringToSign> GET Wed, 11 May 2011 07:59:25 GMT /oss-example?acl </StringToSign> <OSSAccessKeyId> AKIAIVAKMSMOY7VOMRWQ </OSSAccessKeyId> </Error> 说明 OSS SDK已经实现签名,用户使用OSS SDK不需要关注签名问题。如果您想了解具体语言的签名实现,请参考OSS SDK的代码。OSS SDK签名实现的文件如下表: SDK 签名实现 Java SDK OSSRequestSigner.java Python SDK auth.py .Net SDK OssRequestSigner.cs PHP SDK OssClient.php C SDK oss_auth.c JavaScript SDK client.js Go SDK auth.go Ruby SDK util.rb iOS SDK OSSModel.m Android SDK OSSUtils.java 当您自己实现签名,访问OSS报 SignatureDoesNotMatch 错误时,请使用可视化签名工具确认签名并排除错误。 常见问题 Content-MD5的计算方法 Content-MD5的计算 以消息内容为"123456789"来说,计算这个字符串的Content-MD5 正确的计算方式: 标准中定义的算法简单点说就是: 1. 先计算MD5加密的二进制数组(128位)。 2. 再对这个二进制进行base64编码(而不是对32位字符串编码)。 以Python为例子: 正确计算的代码为: >>> import base64,hashlib >>> hash = hashlib.md5() >>> hash.update("0123456789") >>> base64.b64encode(hash.digest()) 'eB5eJF1ptWaXm4bijSPyxw==' 需要注意 正确的是:hash.digest(),计算出进制数组(128位) >>> hash.digest() 'x\x1e^$]i\xb5f\x97\x9b\x86\xe2\x8d#\xf2\xc7' 常见错误是直接对计算出的32位字符串编码进行base64编码。 例如,错误的是:hash.hexdigest(),计算得到可见的32位字符串编码 >>> hash.hexdigest() '781e5e245d69b566979b86e28d23f2c7' 错误的MD5值进行base64编码后的结果: >>> base64.b64encode(hash.hexdigest()) 'NzgxZTVlMjQ1ZDY5YjU2Njk3OWI4NmUyOGQyM2YyYzc='

2019-12-01 23:13:44 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档 用户可以在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-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错误。 构建CanonicalizedOSSHeaders的方法 所有以 x-oss- 为前缀的HTTP Header被称为CanonicalizedOSSHeaders。它的构建方法如下: 将所有以 x-oss- 为前缀的HTTP请求头的名字转换成 小写 。如X-OSS-Meta-Name: TaoBao转换成x-oss-meta-name: TaoBao。 如果请求是以STS获得的AccessKeyId和AccessKeySecret发送时,还需要将获得的security-token值,以 x-oss-security-token:security-token 的形式加入到签名字符串中。 将上一步得到的所有HTTP请求头按照名字的字典序进行升序排列。 删除请求头和内容之间分隔符两端出现的任何空格。如x-oss-meta-name: TaoBao转换成:x-oss-meta-name:TaoBao。 将每一个头和内容用 \n 分隔符分隔拼成最后的CanonicalizedOSSHeaders。 说明 CanonicalizedOSSHeaders可以为空,无需添加最后的 \n。 如果只有一个,则如 x-oss-meta-a\n,注意最后的\n。 如果有多个,则如 x-oss-meta-a:a\nx-oss-meta-b:b\nx-oss-meta-c:c\n, 注意最后的\n。 构建CanonicalizedResource的方法 用户发送请求中想访问的OSS目标资源被称为CanonicalizedResource。它的构建方法如下: 将CanonicalizedResource置成空字符串 ""; 放入要访问的OSS资源 /BucketName/ObjectName(无ObjectName则CanonicalizedResource为”/BucketName/“,如果同时也没有BucketName则为“/”) 如果请求的资源包括子资源(SubResource) ,那么将所有的子资源按照字典序,从小到大排列并以 & 为分隔符生成子资源字符串。在CanonicalizedResource字符串尾添加 ?和子资源字符串。此时的CanonicalizedResource如:/BucketName/ObjectName?acl&uploadId=UploadId 如果用户请求在指定了查询字符串(QueryString,也叫Http Request Parameters),那么将这些查询字符串及其请求值按照 字典序,从小到大排列,以 & 为分隔符,按参数添加到CanonicalizedResource中。此时的CanonicalizedResource如:/BucketName/ObjectName?acl&response-content-type=ContentType&uploadId=UploadId。 说明 OSS目前支持的子资源(sub-resource)包括:acl,uploads,location,cors,logging,website,referer,lifecycle,delete,append,tagging,objectMeta,uploadId,partNumber,security-token,position,img,style,styleName,replication,replicationProgress,replicationLocation,cname,bucketInfo,comp,qos,live,status,vod,startTime,endTime,symlink,x-oss-process,response-content-type,response-content-language,response-expires,response-cache-control,response-content-disposition,response-content-encoding等 子资源(sub-resource)有三种类型: 资源标识,如子资源中的acl,append,uploadId,symlink等,详见关于Bucket的操作和关于Object的操作。 指定返回Header字段,如 response-***,详见GetObject的Request Parameters。 文件(Object)处理方式,如 x-oss-process,用于文件的处理方式,如图片处理。 计算签名头规则 签名的字符串必须为 UTF-8 格式。含有中文字符的签名字符串必须先进行 UTF-8 编码,再与 AccessKeySecret计算最终签名。 签名的方法用RFC 2104中定义的HMAC-SHA1方法,其中Key为 AccessKeySecret` 。 Content-Type 和 Content-MD5 在请求中不是必须的,但是如果请求需要签名验证,空值的话以换行符 \n 代替。 在所有非HTTP标准定义的header中,只有以 x-oss- 开头的header,需要加入签名字符串;其他非HTTP标准header将被OSS忽略(如上例中的x-oss-magic是需要加入签名字符串的)。 以 x-oss- 开头的header在签名验证前需要符合以下规范: header的名字需要变成小写。 header按字典序自小到大排序。 分割header name和value的冒号前后不能有空格。 每个Header之后都有一个换行符“\n”,如果没有Header,CanonicalizedOSSHeaders就设置为空。 签名示例 假如AccessKeyId是”44CF9590006BF252F707”,AccessKeySecret是”OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV” 请求 签名字符串计算公式 签名字符串 PUT /nelson HTTP/1.0 Content-MD5: eB5eJF1ptWaXm4bijSPyxw== Content-Type: text/html Date: Thu, 17 Nov 2005 18:49:58 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com X-OSS-Meta-Author: foo@bar.com X-OSS-Magic: abracadabra Signature = base64(hmac-sha1(AccessKeySecret,VERB + “\n” + Content-MD5 + “\n”+ Content-Type + “\n” + Date + “\n” + CanonicalizedOSSHeaders+ CanonicalizedResource)) “PUT\n eB5eJF1ptWaXm4bijSPyxw==\n text/html\n Thu, 17 Nov 2005 18:49:58 GMT\n x-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n/oss-example/nels 可用以下方法计算签名(Signature): python示例代码: import base64 import hmac import sha h = hmac.new("OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV", "PUT\nODBGOERFMDMzQTczRUY3NUE3NzA5QzdFNUYzMDQxNEM=\ntext/html\nThu, 17 Nov 2005 18:49:58 GMT\nx-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n/oss-example/nelson", sha) Signature = base64.b64encode(h.digest()) print("Signature: %s" % Signature) 签名(Signature)计算结果应该为 26NBxoKdsyly4EDv6inkoDft/yA=,因为Authorization = “OSS “ + AccessKeyId + “:” + Signature所以最后Authorization为 “OSS 44CF9590006BF252F707:26NBxoKdsyly4EDv6inkoDft/yA=”然后加上Authorization头来组成最后需要发送的消息: PUT /nelson HTTP/1.0 Authorization:OSS 44CF9590006BF252F707:26NBxoKdsyly4EDv6inkoDft/yA= Content-Md5: eB5eJF1ptWaXm4bijSPyxw== Content-Type: text/html Date: Thu, 17 Nov 2005 18:49:58 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com X-OSS-Meta-Author: foo@bar.com X-OSS-Magic: abracadabra 细节分析 如果传入的AccessKeyId不存在或inactive,返回403 Forbidden。错误码:InvalidAccessKeyId。 若用户请求头中Authorization值的格式不对,返回400 Bad Request。错误码:InvalidArgument。 OSS所有的请求都必须使用HTTP 1.1协议规定的GMT时间格式。其中,日期的格式为:date1 = 2DIGIT SP month SP 4DIGIT; day month year (e.g., 02 Jun 1982)上述日期格式中,“天”所占位数都是“2 DIGIT”。因此,“Jun 2”、“2 Jun 1982”和“2-Jun-82”都是非法日期格式。 如果签名验证的时候,头中没有传入Date或者格式不正确,返回403 Forbidden错误。错误码:AccessDenied。 传入请求的时间必须在OSS服务器当前时间之后的15分钟以内,否则返回403 Forbidden。错误码:RequestTimeTooSkewed。 如果AccessKeyId是active的,但OSS判断用户的请求发生签名错误,则返回403 Forbidden,并在返回给用户的response中告诉用户正确的用于验证加密的签名字符串。用户可以根据OSS的response来检查自己的签名字符串是否正确。返回示例:<?xml version="1.0" ?> <Error> <Code> SignatureDoesNotMatch </Code> <Message> The request signature we calculated does not match the signature you provided. Check your key and signing method. </Message> <StringToSignBytes> 47 45 54 0a 0a 0a 57 65 64 2c 20 31 31 20 4d 61 79 20 32 30 31 31 20 30 37 3a 35 39 3a 32 35 20 47 4d 54 0a 2f 75 73 72 65 61 6c 74 65 73 74 3f 61 63 6c </StringToSignBytes> <RequestId> 1E446260FF9B10C2 </RequestId> <HostId> oss-cn-hangzhou.aliyuncs.com </HostId> <SignatureProvided> y5H7yzPsA/tP4+0tH1HHvPEwUv8= </SignatureProvided> <StringToSign> GET Wed, 11 May 2011 07:59:25 GMT /oss-example?acl </StringToSign> <OSSAccessKeyId> AKIAIVAKMSMOY7VOMRWQ </OSSAccessKeyId> </Error> 说明 OSS SDK已经实现签名,用户使用OSS SDK不需要关注签名问题。如果您想了解具体语言的签名实现,请参考OSS SDK的代码。OSS SDK签名实现的文件如下表: SDK 签名实现 Java SDK OSSRequestSigner.java Python SDK auth.py .Net SDK OssRequestSigner.cs PHP SDK OssClient.php C SDK oss_auth.c JavaScript SDK client.js Go SDK auth.go Ruby SDK util.rb iOS SDK OSSModel.m Android SDK OSSUtils.java 当您自己实现签名,访问OSS报 SignatureDoesNotMatch 错误时,请使用可视化签名工具确认签名并排除错误。 常见问题 Content-MD5的计算方法 Content-MD5的计算 以消息内容为"123456789"来说,计算这个字符串的Content-MD5 正确的计算方式: 标准中定义的算法简单点说就是: 1. 先计算MD5加密的二进制数组(128位)。 2. 再对这个二进制进行base64编码(而不是对32位字符串编码)。 以Python为例子: 正确计算的代码为: >>> import base64,hashlib >>> hash = hashlib.md5() >>> hash.update("0123456789") >>> base64.b64encode(hash.digest()) 'eB5eJF1ptWaXm4bijSPyxw==' 需要注意 正确的是:hash.digest(),计算出进制数组(128位) >>> hash.digest() 'x\x1e^$]i\xb5f\x97\x9b\x86\xe2\x8d#\xf2\xc7' 常见错误是直接对计算出的32位字符串编码进行base64编码。 例如,错误的是:hash.hexdigest(),计算得到可见的32位字符串编码 >>> hash.hexdigest() '781e5e245d69b566979b86e28d23f2c7' 错误的MD5值进行base64编码后的结果: >>> base64.b64encode(hash.hexdigest()) 'NzgxZTVlMjQ1ZDY5YjU2Njk3OWI4NmUyOGQyM2YyYzc='

2019-12-01 23:13:45 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档 用户可以在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-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错误。 构建CanonicalizedOSSHeaders的方法 所有以 x-oss- 为前缀的HTTP Header被称为CanonicalizedOSSHeaders。它的构建方法如下: 将所有以 x-oss- 为前缀的HTTP请求头的名字转换成 小写 。如X-OSS-Meta-Name: TaoBao转换成x-oss-meta-name: TaoBao。 如果请求是以STS获得的AccessKeyId和AccessKeySecret发送时,还需要将获得的security-token值,以 x-oss-security-token:security-token 的形式加入到签名字符串中。 将上一步得到的所有HTTP请求头按照名字的字典序进行升序排列。 删除请求头和内容之间分隔符两端出现的任何空格。如x-oss-meta-name: TaoBao转换成:x-oss-meta-name:TaoBao。 将每一个头和内容用 \n 分隔符分隔拼成最后的CanonicalizedOSSHeaders。 说明 CanonicalizedOSSHeaders可以为空,无需添加最后的 \n。 如果只有一个,则如 x-oss-meta-a\n,注意最后的\n。 如果有多个,则如 x-oss-meta-a:a\nx-oss-meta-b:b\nx-oss-meta-c:c\n, 注意最后的\n。 构建CanonicalizedResource的方法 用户发送请求中想访问的OSS目标资源被称为CanonicalizedResource。它的构建方法如下: 将CanonicalizedResource置成空字符串 ""; 放入要访问的OSS资源 /BucketName/ObjectName(无ObjectName则CanonicalizedResource为”/BucketName/“,如果同时也没有BucketName则为“/”) 如果请求的资源包括子资源(SubResource) ,那么将所有的子资源按照字典序,从小到大排列并以 & 为分隔符生成子资源字符串。在CanonicalizedResource字符串尾添加 ?和子资源字符串。此时的CanonicalizedResource如:/BucketName/ObjectName?acl&uploadId=UploadId 如果用户请求在指定了查询字符串(QueryString,也叫Http Request Parameters),那么将这些查询字符串及其请求值按照 字典序,从小到大排列,以 & 为分隔符,按参数添加到CanonicalizedResource中。此时的CanonicalizedResource如:/BucketName/ObjectName?acl&response-content-type=ContentType&uploadId=UploadId。 说明 OSS目前支持的子资源(sub-resource)包括:acl,uploads,location,cors,logging,website,referer,lifecycle,delete,append,tagging,objectMeta,uploadId,partNumber,security-token,position,img,style,styleName,replication,replicationProgress,replicationLocation,cname,bucketInfo,comp,qos,live,status,vod,startTime,endTime,symlink,x-oss-process,response-content-type,response-content-language,response-expires,response-cache-control,response-content-disposition,response-content-encoding等 子资源(sub-resource)有三种类型: 资源标识,如子资源中的acl,append,uploadId,symlink等,详见关于Bucket的操作和关于Object的操作。 指定返回Header字段,如 response-***,详见GetObject的Request Parameters。 文件(Object)处理方式,如 x-oss-process,用于文件的处理方式,如图片处理。 计算签名头规则 签名的字符串必须为 UTF-8 格式。含有中文字符的签名字符串必须先进行 UTF-8 编码,再与 AccessKeySecret计算最终签名。 签名的方法用RFC 2104中定义的HMAC-SHA1方法,其中Key为 AccessKeySecret` 。 Content-Type 和 Content-MD5 在请求中不是必须的,但是如果请求需要签名验证,空值的话以换行符 \n 代替。 在所有非HTTP标准定义的header中,只有以 x-oss- 开头的header,需要加入签名字符串;其他非HTTP标准header将被OSS忽略(如上例中的x-oss-magic是需要加入签名字符串的)。 以 x-oss- 开头的header在签名验证前需要符合以下规范: header的名字需要变成小写。 header按字典序自小到大排序。 分割header name和value的冒号前后不能有空格。 每个Header之后都有一个换行符“\n”,如果没有Header,CanonicalizedOSSHeaders就设置为空。 签名示例 假如AccessKeyId是”44CF9590006BF252F707”,AccessKeySecret是”OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV” 请求 签名字符串计算公式 签名字符串 PUT /nelson HTTP/1.0 Content-MD5: eB5eJF1ptWaXm4bijSPyxw== Content-Type: text/html Date: Thu, 17 Nov 2005 18:49:58 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com X-OSS-Meta-Author: foo@bar.com X-OSS-Magic: abracadabra Signature = base64(hmac-sha1(AccessKeySecret,VERB + “\n” + Content-MD5 + “\n”+ Content-Type + “\n” + Date + “\n” + CanonicalizedOSSHeaders+ CanonicalizedResource)) “PUT\n eB5eJF1ptWaXm4bijSPyxw==\n text/html\n Thu, 17 Nov 2005 18:49:58 GMT\n x-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n/oss-example/nels 可用以下方法计算签名(Signature): python示例代码: import base64 import hmac import sha h = hmac.new("OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV", "PUT\nODBGOERFMDMzQTczRUY3NUE3NzA5QzdFNUYzMDQxNEM=\ntext/html\nThu, 17 Nov 2005 18:49:58 GMT\nx-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n/oss-example/nelson", sha) Signature = base64.b64encode(h.digest()) print("Signature: %s" % Signature) 签名(Signature)计算结果应该为 26NBxoKdsyly4EDv6inkoDft/yA=,因为Authorization = “OSS “ + AccessKeyId + “:” + Signature所以最后Authorization为 “OSS 44CF9590006BF252F707:26NBxoKdsyly4EDv6inkoDft/yA=”然后加上Authorization头来组成最后需要发送的消息: PUT /nelson HTTP/1.0 Authorization:OSS 44CF9590006BF252F707:26NBxoKdsyly4EDv6inkoDft/yA= Content-Md5: eB5eJF1ptWaXm4bijSPyxw== Content-Type: text/html Date: Thu, 17 Nov 2005 18:49:58 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com X-OSS-Meta-Author: foo@bar.com X-OSS-Magic: abracadabra 细节分析 如果传入的AccessKeyId不存在或inactive,返回403 Forbidden。错误码:InvalidAccessKeyId。 若用户请求头中Authorization值的格式不对,返回400 Bad Request。错误码:InvalidArgument。 OSS所有的请求都必须使用HTTP 1.1协议规定的GMT时间格式。其中,日期的格式为:date1 = 2DIGIT SP month SP 4DIGIT; day month year (e.g., 02 Jun 1982)上述日期格式中,“天”所占位数都是“2 DIGIT”。因此,“Jun 2”、“2 Jun 1982”和“2-Jun-82”都是非法日期格式。 如果签名验证的时候,头中没有传入Date或者格式不正确,返回403 Forbidden错误。错误码:AccessDenied。 传入请求的时间必须在OSS服务器当前时间之后的15分钟以内,否则返回403 Forbidden。错误码:RequestTimeTooSkewed。 如果AccessKeyId是active的,但OSS判断用户的请求发生签名错误,则返回403 Forbidden,并在返回给用户的response中告诉用户正确的用于验证加密的签名字符串。用户可以根据OSS的response来检查自己的签名字符串是否正确。返回示例:<?xml version="1.0" ?> <Error> <Code> SignatureDoesNotMatch </Code> <Message> The request signature we calculated does not match the signature you provided. Check your key and signing method. </Message> <StringToSignBytes> 47 45 54 0a 0a 0a 57 65 64 2c 20 31 31 20 4d 61 79 20 32 30 31 31 20 30 37 3a 35 39 3a 32 35 20 47 4d 54 0a 2f 75 73 72 65 61 6c 74 65 73 74 3f 61 63 6c </StringToSignBytes> <RequestId> 1E446260FF9B10C2 </RequestId> <HostId> oss-cn-hangzhou.aliyuncs.com </HostId> <SignatureProvided> y5H7yzPsA/tP4+0tH1HHvPEwUv8= </SignatureProvided> <StringToSign> GET Wed, 11 May 2011 07:59:25 GMT /oss-example?acl </StringToSign> <OSSAccessKeyId> AKIAIVAKMSMOY7VOMRWQ </OSSAccessKeyId> </Error> 说明 OSS SDK已经实现签名,用户使用OSS SDK不需要关注签名问题。如果您想了解具体语言的签名实现,请参考OSS SDK的代码。OSS SDK签名实现的文件如下表: SDK 签名实现 Java SDK OSSRequestSigner.java Python SDK auth.py .Net SDK OssRequestSigner.cs PHP SDK OssClient.php C SDK oss_auth.c JavaScript SDK client.js Go SDK auth.go Ruby SDK util.rb iOS SDK OSSModel.m Android SDK OSSUtils.java 当您自己实现签名,访问OSS报 SignatureDoesNotMatch 错误时,请使用可视化签名工具确认签名并排除错误。 常见问题 Content-MD5的计算方法 Content-MD5的计算 以消息内容为"123456789"来说,计算这个字符串的Content-MD5 正确的计算方式: 标准中定义的算法简单点说就是: 1. 先计算MD5加密的二进制数组(128位)。 2. 再对这个二进制进行base64编码(而不是对32位字符串编码)。 以Python为例子: 正确计算的代码为: >>> import base64,hashlib >>> hash = hashlib.md5() >>> hash.update("0123456789") >>> base64.b64encode(hash.digest()) 'eB5eJF1ptWaXm4bijSPyxw==' 需要注意 正确的是:hash.digest(),计算出进制数组(128位) >>> hash.digest() 'x\x1e^$]i\xb5f\x97\x9b\x86\xe2\x8d#\xf2\xc7' 常见错误是直接对计算出的32位字符串编码进行base64编码。 例如,错误的是:hash.hexdigest(),计算得到可见的32位字符串编码 >>> hash.hexdigest() '781e5e245d69b566979b86e28d23f2c7' 错误的MD5值进行base64编码后的结果: >>> base64.b64encode(hash.hexdigest()) 'NzgxZTVlMjQ1ZDY5YjU2Njk3OWI4NmUyOGQyM2YyYzc='

2019-12-01 23:13:44 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档 用户可以在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-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错误。 构建CanonicalizedOSSHeaders的方法 所有以 x-oss- 为前缀的HTTP Header被称为CanonicalizedOSSHeaders。它的构建方法如下: 将所有以 x-oss- 为前缀的HTTP请求头的名字转换成 小写 。如X-OSS-Meta-Name: TaoBao转换成x-oss-meta-name: TaoBao。 如果请求是以STS获得的AccessKeyId和AccessKeySecret发送时,还需要将获得的security-token值,以 x-oss-security-token:security-token 的形式加入到签名字符串中。 将上一步得到的所有HTTP请求头按照名字的字典序进行升序排列。 删除请求头和内容之间分隔符两端出现的任何空格。如x-oss-meta-name: TaoBao转换成:x-oss-meta-name:TaoBao。 将每一个头和内容用 \n 分隔符分隔拼成最后的CanonicalizedOSSHeaders。 说明 CanonicalizedOSSHeaders可以为空,无需添加最后的 \n。 如果只有一个,则如 x-oss-meta-a\n,注意最后的\n。 如果有多个,则如 x-oss-meta-a:a\nx-oss-meta-b:b\nx-oss-meta-c:c\n, 注意最后的\n。 构建CanonicalizedResource的方法 用户发送请求中想访问的OSS目标资源被称为CanonicalizedResource。它的构建方法如下: 将CanonicalizedResource置成空字符串 ""; 放入要访问的OSS资源 /BucketName/ObjectName(无ObjectName则CanonicalizedResource为”/BucketName/“,如果同时也没有BucketName则为“/”) 如果请求的资源包括子资源(SubResource) ,那么将所有的子资源按照字典序,从小到大排列并以 & 为分隔符生成子资源字符串。在CanonicalizedResource字符串尾添加 ?和子资源字符串。此时的CanonicalizedResource如:/BucketName/ObjectName?acl&uploadId=UploadId 如果用户请求在指定了查询字符串(QueryString,也叫Http Request Parameters),那么将这些查询字符串及其请求值按照 字典序,从小到大排列,以 & 为分隔符,按参数添加到CanonicalizedResource中。此时的CanonicalizedResource如:/BucketName/ObjectName?acl&response-content-type=ContentType&uploadId=UploadId。 说明 OSS目前支持的子资源(sub-resource)包括:acl,uploads,location,cors,logging,website,referer,lifecycle,delete,append,tagging,objectMeta,uploadId,partNumber,security-token,position,img,style,styleName,replication,replicationProgress,replicationLocation,cname,bucketInfo,comp,qos,live,status,vod,startTime,endTime,symlink,x-oss-process,response-content-type,response-content-language,response-expires,response-cache-control,response-content-disposition,response-content-encoding等 子资源(sub-resource)有三种类型: 资源标识,如子资源中的acl,append,uploadId,symlink等,详见关于Bucket的操作和关于Object的操作。 指定返回Header字段,如 response-***,详见GetObject的Request Parameters。 文件(Object)处理方式,如 x-oss-process,用于文件的处理方式,如图片处理。 计算签名头规则 签名的字符串必须为 UTF-8 格式。含有中文字符的签名字符串必须先进行 UTF-8 编码,再与 AccessKeySecret计算最终签名。 签名的方法用RFC 2104中定义的HMAC-SHA1方法,其中Key为 AccessKeySecret` 。 Content-Type 和 Content-MD5 在请求中不是必须的,但是如果请求需要签名验证,空值的话以换行符 \n 代替。 在所有非HTTP标准定义的header中,只有以 x-oss- 开头的header,需要加入签名字符串;其他非HTTP标准header将被OSS忽略(如上例中的x-oss-magic是需要加入签名字符串的)。 以 x-oss- 开头的header在签名验证前需要符合以下规范: header的名字需要变成小写。 header按字典序自小到大排序。 分割header name和value的冒号前后不能有空格。 每个Header之后都有一个换行符“\n”,如果没有Header,CanonicalizedOSSHeaders就设置为空。 签名示例 假如AccessKeyId是”44CF9590006BF252F707”,AccessKeySecret是”OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV” 请求 签名字符串计算公式 签名字符串 PUT /nelson HTTP/1.0 Content-MD5: eB5eJF1ptWaXm4bijSPyxw== Content-Type: text/html Date: Thu, 17 Nov 2005 18:49:58 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com X-OSS-Meta-Author: foo@bar.com X-OSS-Magic: abracadabra Signature = base64(hmac-sha1(AccessKeySecret,VERB + “\n” + Content-MD5 + “\n”+ Content-Type + “\n” + Date + “\n” + CanonicalizedOSSHeaders+ CanonicalizedResource)) “PUT\n eB5eJF1ptWaXm4bijSPyxw==\n text/html\n Thu, 17 Nov 2005 18:49:58 GMT\n x-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n/oss-example/nels 可用以下方法计算签名(Signature): python示例代码: import base64 import hmac import sha h = hmac.new("OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV", "PUT\nODBGOERFMDMzQTczRUY3NUE3NzA5QzdFNUYzMDQxNEM=\ntext/html\nThu, 17 Nov 2005 18:49:58 GMT\nx-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n/oss-example/nelson", sha) Signature = base64.b64encode(h.digest()) print("Signature: %s" % Signature) 签名(Signature)计算结果应该为 26NBxoKdsyly4EDv6inkoDft/yA=,因为Authorization = “OSS “ + AccessKeyId + “:” + Signature所以最后Authorization为 “OSS 44CF9590006BF252F707:26NBxoKdsyly4EDv6inkoDft/yA=”然后加上Authorization头来组成最后需要发送的消息: PUT /nelson HTTP/1.0 Authorization:OSS 44CF9590006BF252F707:26NBxoKdsyly4EDv6inkoDft/yA= Content-Md5: eB5eJF1ptWaXm4bijSPyxw== Content-Type: text/html Date: Thu, 17 Nov 2005 18:49:58 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com X-OSS-Meta-Author: foo@bar.com X-OSS-Magic: abracadabra 细节分析 如果传入的AccessKeyId不存在或inactive,返回403 Forbidden。错误码:InvalidAccessKeyId。 若用户请求头中Authorization值的格式不对,返回400 Bad Request。错误码:InvalidArgument。 OSS所有的请求都必须使用HTTP 1.1协议规定的GMT时间格式。其中,日期的格式为:date1 = 2DIGIT SP month SP 4DIGIT; day month year (e.g., 02 Jun 1982)上述日期格式中,“天”所占位数都是“2 DIGIT”。因此,“Jun 2”、“2 Jun 1982”和“2-Jun-82”都是非法日期格式。 如果签名验证的时候,头中没有传入Date或者格式不正确,返回403 Forbidden错误。错误码:AccessDenied。 传入请求的时间必须在OSS服务器当前时间之后的15分钟以内,否则返回403 Forbidden。错误码:RequestTimeTooSkewed。 如果AccessKeyId是active的,但OSS判断用户的请求发生签名错误,则返回403 Forbidden,并在返回给用户的response中告诉用户正确的用于验证加密的签名字符串。用户可以根据OSS的response来检查自己的签名字符串是否正确。返回示例:<?xml version="1.0" ?> <Error> <Code> SignatureDoesNotMatch </Code> <Message> The request signature we calculated does not match the signature you provided. Check your key and signing method. </Message> <StringToSignBytes> 47 45 54 0a 0a 0a 57 65 64 2c 20 31 31 20 4d 61 79 20 32 30 31 31 20 30 37 3a 35 39 3a 32 35 20 47 4d 54 0a 2f 75 73 72 65 61 6c 74 65 73 74 3f 61 63 6c </StringToSignBytes> <RequestId> 1E446260FF9B10C2 </RequestId> <HostId> oss-cn-hangzhou.aliyuncs.com </HostId> <SignatureProvided> y5H7yzPsA/tP4+0tH1HHvPEwUv8= </SignatureProvided> <StringToSign> GET Wed, 11 May 2011 07:59:25 GMT /oss-example?acl </StringToSign> <OSSAccessKeyId> AKIAIVAKMSMOY7VOMRWQ </OSSAccessKeyId> </Error> 说明 OSS SDK已经实现签名,用户使用OSS SDK不需要关注签名问题。如果您想了解具体语言的签名实现,请参考OSS SDK的代码。OSS SDK签名实现的文件如下表: SDK 签名实现 Java SDK OSSRequestSigner.java Python SDK auth.py .Net SDK OssRequestSigner.cs PHP SDK OssClient.php C SDK oss_auth.c JavaScript SDK client.js Go SDK auth.go Ruby SDK util.rb iOS SDK OSSModel.m Android SDK OSSUtils.java 当您自己实现签名,访问OSS报 SignatureDoesNotMatch 错误时,请使用可视化签名工具确认签名并排除错误。 常见问题 Content-MD5的计算方法 Content-MD5的计算 以消息内容为"123456789"来说,计算这个字符串的Content-MD5 正确的计算方式: 标准中定义的算法简单点说就是: 1. 先计算MD5加密的二进制数组(128位)。 2. 再对这个二进制进行base64编码(而不是对32位字符串编码)。 以Python为例子: 正确计算的代码为: >>> import base64,hashlib >>> hash = hashlib.md5() >>> hash.update("0123456789") >>> base64.b64encode(hash.digest()) 'eB5eJF1ptWaXm4bijSPyxw==' 需要注意 正确的是:hash.digest(),计算出进制数组(128位) >>> hash.digest() 'x\x1e^$]i\xb5f\x97\x9b\x86\xe2\x8d#\xf2\xc7' 常见错误是直接对计算出的32位字符串编码进行base64编码。 例如,错误的是:hash.hexdigest(),计算得到可见的32位字符串编码 >>> hash.hexdigest() '781e5e245d69b566979b86e28d23f2c7' 错误的MD5值进行base64编码后的结果: >>> base64.b64encode(hash.hexdigest()) 'NzgxZTVlMjQ1ZDY5YjU2Njk3OWI4NmUyOGQyM2YyYzc='

2019-12-01 23:13:44 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档 用户可以在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-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错误。 构建CanonicalizedOSSHeaders的方法 所有以 x-oss- 为前缀的HTTP Header被称为CanonicalizedOSSHeaders。它的构建方法如下: 将所有以 x-oss- 为前缀的HTTP请求头的名字转换成 小写 。如X-OSS-Meta-Name: TaoBao转换成x-oss-meta-name: TaoBao。 如果请求是以STS获得的AccessKeyId和AccessKeySecret发送时,还需要将获得的security-token值,以 x-oss-security-token:security-token 的形式加入到签名字符串中。 将上一步得到的所有HTTP请求头按照名字的字典序进行升序排列。 删除请求头和内容之间分隔符两端出现的任何空格。如x-oss-meta-name: TaoBao转换成:x-oss-meta-name:TaoBao。 将每一个头和内容用 \n 分隔符分隔拼成最后的CanonicalizedOSSHeaders。 说明 CanonicalizedOSSHeaders可以为空,无需添加最后的 \n。 如果只有一个,则如 x-oss-meta-a\n,注意最后的\n。 如果有多个,则如 x-oss-meta-a:a\nx-oss-meta-b:b\nx-oss-meta-c:c\n, 注意最后的\n。 构建CanonicalizedResource的方法 用户发送请求中想访问的OSS目标资源被称为CanonicalizedResource。它的构建方法如下: 将CanonicalizedResource置成空字符串 ""; 放入要访问的OSS资源 /BucketName/ObjectName(无ObjectName则CanonicalizedResource为”/BucketName/“,如果同时也没有BucketName则为“/”) 如果请求的资源包括子资源(SubResource) ,那么将所有的子资源按照字典序,从小到大排列并以 & 为分隔符生成子资源字符串。在CanonicalizedResource字符串尾添加 ?和子资源字符串。此时的CanonicalizedResource如:/BucketName/ObjectName?acl&uploadId=UploadId 如果用户请求在指定了查询字符串(QueryString,也叫Http Request Parameters),那么将这些查询字符串及其请求值按照 字典序,从小到大排列,以 & 为分隔符,按参数添加到CanonicalizedResource中。此时的CanonicalizedResource如:/BucketName/ObjectName?acl&response-content-type=ContentType&uploadId=UploadId。 说明 OSS目前支持的子资源(sub-resource)包括:acl,uploads,location,cors,logging,website,referer,lifecycle,delete,append,tagging,objectMeta,uploadId,partNumber,security-token,position,img,style,styleName,replication,replicationProgress,replicationLocation,cname,bucketInfo,comp,qos,live,status,vod,startTime,endTime,symlink,x-oss-process,response-content-type,response-content-language,response-expires,response-cache-control,response-content-disposition,response-content-encoding等 子资源(sub-resource)有三种类型: 资源标识,如子资源中的acl,append,uploadId,symlink等,详见关于Bucket的操作和关于Object的操作。 指定返回Header字段,如 response-***,详见GetObject的Request Parameters。 文件(Object)处理方式,如 x-oss-process,用于文件的处理方式,如图片处理。 计算签名头规则 签名的字符串必须为 UTF-8 格式。含有中文字符的签名字符串必须先进行 UTF-8 编码,再与 AccessKeySecret计算最终签名。 签名的方法用RFC 2104中定义的HMAC-SHA1方法,其中Key为 AccessKeySecret` 。 Content-Type 和 Content-MD5 在请求中不是必须的,但是如果请求需要签名验证,空值的话以换行符 \n 代替。 在所有非HTTP标准定义的header中,只有以 x-oss- 开头的header,需要加入签名字符串;其他非HTTP标准header将被OSS忽略(如上例中的x-oss-magic是需要加入签名字符串的)。 以 x-oss- 开头的header在签名验证前需要符合以下规范: header的名字需要变成小写。 header按字典序自小到大排序。 分割header name和value的冒号前后不能有空格。 每个Header之后都有一个换行符“\n”,如果没有Header,CanonicalizedOSSHeaders就设置为空。 签名示例 假如AccessKeyId是”44CF9590006BF252F707”,AccessKeySecret是”OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV” 请求 签名字符串计算公式 签名字符串 PUT /nelson HTTP/1.0 Content-MD5: eB5eJF1ptWaXm4bijSPyxw== Content-Type: text/html Date: Thu, 17 Nov 2005 18:49:58 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com X-OSS-Meta-Author: foo@bar.com X-OSS-Magic: abracadabra Signature = base64(hmac-sha1(AccessKeySecret,VERB + “\n” + Content-MD5 + “\n”+ Content-Type + “\n” + Date + “\n” + CanonicalizedOSSHeaders+ CanonicalizedResource)) “PUT\n eB5eJF1ptWaXm4bijSPyxw==\n text/html\n Thu, 17 Nov 2005 18:49:58 GMT\n x-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n/oss-example/nels 可用以下方法计算签名(Signature): python示例代码: import base64 import hmac import sha h = hmac.new("OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV", "PUT\nODBGOERFMDMzQTczRUY3NUE3NzA5QzdFNUYzMDQxNEM=\ntext/html\nThu, 17 Nov 2005 18:49:58 GMT\nx-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n/oss-example/nelson", sha) Signature = base64.b64encode(h.digest()) print("Signature: %s" % Signature) 签名(Signature)计算结果应该为 26NBxoKdsyly4EDv6inkoDft/yA=,因为Authorization = “OSS “ + AccessKeyId + “:” + Signature所以最后Authorization为 “OSS 44CF9590006BF252F707:26NBxoKdsyly4EDv6inkoDft/yA=”然后加上Authorization头来组成最后需要发送的消息: PUT /nelson HTTP/1.0 Authorization:OSS 44CF9590006BF252F707:26NBxoKdsyly4EDv6inkoDft/yA= Content-Md5: eB5eJF1ptWaXm4bijSPyxw== Content-Type: text/html Date: Thu, 17 Nov 2005 18:49:58 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com X-OSS-Meta-Author: foo@bar.com X-OSS-Magic: abracadabra 细节分析 如果传入的AccessKeyId不存在或inactive,返回403 Forbidden。错误码:InvalidAccessKeyId。 若用户请求头中Authorization值的格式不对,返回400 Bad Request。错误码:InvalidArgument。 OSS所有的请求都必须使用HTTP 1.1协议规定的GMT时间格式。其中,日期的格式为:date1 = 2DIGIT SP month SP 4DIGIT; day month year (e.g., 02 Jun 1982)上述日期格式中,“天”所占位数都是“2 DIGIT”。因此,“Jun 2”、“2 Jun 1982”和“2-Jun-82”都是非法日期格式。 如果签名验证的时候,头中没有传入Date或者格式不正确,返回403 Forbidden错误。错误码:AccessDenied。 传入请求的时间必须在OSS服务器当前时间之后的15分钟以内,否则返回403 Forbidden。错误码:RequestTimeTooSkewed。 如果AccessKeyId是active的,但OSS判断用户的请求发生签名错误,则返回403 Forbidden,并在返回给用户的response中告诉用户正确的用于验证加密的签名字符串。用户可以根据OSS的response来检查自己的签名字符串是否正确。返回示例:<?xml version="1.0" ?> <Error> <Code> SignatureDoesNotMatch </Code> <Message> The request signature we calculated does not match the signature you provided. Check your key and signing method. </Message> <StringToSignBytes> 47 45 54 0a 0a 0a 57 65 64 2c 20 31 31 20 4d 61 79 20 32 30 31 31 20 30 37 3a 35 39 3a 32 35 20 47 4d 54 0a 2f 75 73 72 65 61 6c 74 65 73 74 3f 61 63 6c </StringToSignBytes> <RequestId> 1E446260FF9B10C2 </RequestId> <HostId> oss-cn-hangzhou.aliyuncs.com </HostId> <SignatureProvided> y5H7yzPsA/tP4+0tH1HHvPEwUv8= </SignatureProvided> <StringToSign> GET Wed, 11 May 2011 07:59:25 GMT /oss-example?acl </StringToSign> <OSSAccessKeyId> AKIAIVAKMSMOY7VOMRWQ </OSSAccessKeyId> </Error> 说明 OSS SDK已经实现签名,用户使用OSS SDK不需要关注签名问题。如果您想了解具体语言的签名实现,请参考OSS SDK的代码。OSS SDK签名实现的文件如下表: SDK 签名实现 Java SDK OSSRequestSigner.java Python SDK auth.py .Net SDK OssRequestSigner.cs PHP SDK OssClient.php C SDK oss_auth.c JavaScript SDK client.js Go SDK auth.go Ruby SDK util.rb iOS SDK OSSModel.m Android SDK OSSUtils.java 当您自己实现签名,访问OSS报 SignatureDoesNotMatch 错误时,请使用可视化签名工具确认签名并排除错误。 常见问题 Content-MD5的计算方法 Content-MD5的计算 以消息内容为"123456789"来说,计算这个字符串的Content-MD5 正确的计算方式: 标准中定义的算法简单点说就是: 1. 先计算MD5加密的二进制数组(128位)。 2. 再对这个二进制进行base64编码(而不是对32位字符串编码)。 以Python为例子: 正确计算的代码为: >>> import base64,hashlib >>> hash = hashlib.md5() >>> hash.update("0123456789") >>> base64.b64encode(hash.digest()) 'eB5eJF1ptWaXm4bijSPyxw==' 需要注意 正确的是:hash.digest(),计算出进制数组(128位) >>> hash.digest() 'x\x1e^$]i\xb5f\x97\x9b\x86\xe2\x8d#\xf2\xc7' 常见错误是直接对计算出的32位字符串编码进行base64编码。 例如,错误的是:hash.hexdigest(),计算得到可见的32位字符串编码 >>> hash.hexdigest() '781e5e245d69b566979b86e28d23f2c7' 错误的MD5值进行base64编码后的结果: >>> base64.b64encode(hash.hexdigest()) 'NzgxZTVlMjQ1ZDY5YjU2Njk3OWI4NmUyOGQyM2YyYzc='

2019-12-01 23:13:43 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档 用户可以在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-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错误。 构建CanonicalizedOSSHeaders的方法 所有以 x-oss- 为前缀的HTTP Header被称为CanonicalizedOSSHeaders。它的构建方法如下: 将所有以 x-oss- 为前缀的HTTP请求头的名字转换成 小写 。如X-OSS-Meta-Name: TaoBao转换成x-oss-meta-name: TaoBao。 如果请求是以STS获得的AccessKeyId和AccessKeySecret发送时,还需要将获得的security-token值,以 x-oss-security-token:security-token 的形式加入到签名字符串中。 将上一步得到的所有HTTP请求头按照名字的字典序进行升序排列。 删除请求头和内容之间分隔符两端出现的任何空格。如x-oss-meta-name: TaoBao转换成:x-oss-meta-name:TaoBao。 将每一个头和内容用 \n 分隔符分隔拼成最后的CanonicalizedOSSHeaders。 说明 CanonicalizedOSSHeaders可以为空,无需添加最后的 \n。 如果只有一个,则如 x-oss-meta-a\n,注意最后的\n。 如果有多个,则如 x-oss-meta-a:a\nx-oss-meta-b:b\nx-oss-meta-c:c\n, 注意最后的\n。 构建CanonicalizedResource的方法 用户发送请求中想访问的OSS目标资源被称为CanonicalizedResource。它的构建方法如下: 将CanonicalizedResource置成空字符串 ""; 放入要访问的OSS资源 /BucketName/ObjectName(无ObjectName则CanonicalizedResource为”/BucketName/“,如果同时也没有BucketName则为“/”) 如果请求的资源包括子资源(SubResource) ,那么将所有的子资源按照字典序,从小到大排列并以 & 为分隔符生成子资源字符串。在CanonicalizedResource字符串尾添加 ?和子资源字符串。此时的CanonicalizedResource如:/BucketName/ObjectName?acl&uploadId=UploadId 如果用户请求在指定了查询字符串(QueryString,也叫Http Request Parameters),那么将这些查询字符串及其请求值按照 字典序,从小到大排列,以 & 为分隔符,按参数添加到CanonicalizedResource中。此时的CanonicalizedResource如:/BucketName/ObjectName?acl&response-content-type=ContentType&uploadId=UploadId。 说明 OSS目前支持的子资源(sub-resource)包括:acl,uploads,location,cors,logging,website,referer,lifecycle,delete,append,tagging,objectMeta,uploadId,partNumber,security-token,position,img,style,styleName,replication,replicationProgress,replicationLocation,cname,bucketInfo,comp,qos,live,status,vod,startTime,endTime,symlink,x-oss-process,response-content-type,response-content-language,response-expires,response-cache-control,response-content-disposition,response-content-encoding等 子资源(sub-resource)有三种类型: 资源标识,如子资源中的acl,append,uploadId,symlink等,详见关于Bucket的操作和关于Object的操作。 指定返回Header字段,如 response-***,详见GetObject的Request Parameters。 文件(Object)处理方式,如 x-oss-process,用于文件的处理方式,如图片处理。 计算签名头规则 签名的字符串必须为 UTF-8 格式。含有中文字符的签名字符串必须先进行 UTF-8 编码,再与 AccessKeySecret计算最终签名。 签名的方法用RFC 2104中定义的HMAC-SHA1方法,其中Key为 AccessKeySecret` 。 Content-Type 和 Content-MD5 在请求中不是必须的,但是如果请求需要签名验证,空值的话以换行符 \n 代替。 在所有非HTTP标准定义的header中,只有以 x-oss- 开头的header,需要加入签名字符串;其他非HTTP标准header将被OSS忽略(如上例中的x-oss-magic是需要加入签名字符串的)。 以 x-oss- 开头的header在签名验证前需要符合以下规范: header的名字需要变成小写。 header按字典序自小到大排序。 分割header name和value的冒号前后不能有空格。 每个Header之后都有一个换行符“\n”,如果没有Header,CanonicalizedOSSHeaders就设置为空。 签名示例 假如AccessKeyId是”44CF9590006BF252F707”,AccessKeySecret是”OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV” 请求 签名字符串计算公式 签名字符串 PUT /nelson HTTP/1.0 Content-MD5: eB5eJF1ptWaXm4bijSPyxw== Content-Type: text/html Date: Thu, 17 Nov 2005 18:49:58 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com X-OSS-Meta-Author: foo@bar.com X-OSS-Magic: abracadabra Signature = base64(hmac-sha1(AccessKeySecret,VERB + “\n” + Content-MD5 + “\n”+ Content-Type + “\n” + Date + “\n” + CanonicalizedOSSHeaders+ CanonicalizedResource)) “PUT\n eB5eJF1ptWaXm4bijSPyxw==\n text/html\n Thu, 17 Nov 2005 18:49:58 GMT\n x-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n/oss-example/nels 可用以下方法计算签名(Signature): python示例代码: import base64 import hmac import sha h = hmac.new("OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV", "PUT\nODBGOERFMDMzQTczRUY3NUE3NzA5QzdFNUYzMDQxNEM=\ntext/html\nThu, 17 Nov 2005 18:49:58 GMT\nx-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n/oss-example/nelson", sha) Signature = base64.b64encode(h.digest()) print("Signature: %s" % Signature) 签名(Signature)计算结果应该为 26NBxoKdsyly4EDv6inkoDft/yA=,因为Authorization = “OSS “ + AccessKeyId + “:” + Signature所以最后Authorization为 “OSS 44CF9590006BF252F707:26NBxoKdsyly4EDv6inkoDft/yA=”然后加上Authorization头来组成最后需要发送的消息: PUT /nelson HTTP/1.0 Authorization:OSS 44CF9590006BF252F707:26NBxoKdsyly4EDv6inkoDft/yA= Content-Md5: eB5eJF1ptWaXm4bijSPyxw== Content-Type: text/html Date: Thu, 17 Nov 2005 18:49:58 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com X-OSS-Meta-Author: foo@bar.com X-OSS-Magic: abracadabra 细节分析 如果传入的AccessKeyId不存在或inactive,返回403 Forbidden。错误码:InvalidAccessKeyId。 若用户请求头中Authorization值的格式不对,返回400 Bad Request。错误码:InvalidArgument。 OSS所有的请求都必须使用HTTP 1.1协议规定的GMT时间格式。其中,日期的格式为:date1 = 2DIGIT SP month SP 4DIGIT; day month year (e.g., 02 Jun 1982)上述日期格式中,“天”所占位数都是“2 DIGIT”。因此,“Jun 2”、“2 Jun 1982”和“2-Jun-82”都是非法日期格式。 如果签名验证的时候,头中没有传入Date或者格式不正确,返回403 Forbidden错误。错误码:AccessDenied。 传入请求的时间必须在OSS服务器当前时间之后的15分钟以内,否则返回403 Forbidden。错误码:RequestTimeTooSkewed。 如果AccessKeyId是active的,但OSS判断用户的请求发生签名错误,则返回403 Forbidden,并在返回给用户的response中告诉用户正确的用于验证加密的签名字符串。用户可以根据OSS的response来检查自己的签名字符串是否正确。返回示例:<?xml version="1.0" ?> <Error> <Code> SignatureDoesNotMatch </Code> <Message> The request signature we calculated does not match the signature you provided. Check your key and signing method. </Message> <StringToSignBytes> 47 45 54 0a 0a 0a 57 65 64 2c 20 31 31 20 4d 61 79 20 32 30 31 31 20 30 37 3a 35 39 3a 32 35 20 47 4d 54 0a 2f 75 73 72 65 61 6c 74 65 73 74 3f 61 63 6c </StringToSignBytes> <RequestId> 1E446260FF9B10C2 </RequestId> <HostId> oss-cn-hangzhou.aliyuncs.com </HostId> <SignatureProvided> y5H7yzPsA/tP4+0tH1HHvPEwUv8= </SignatureProvided> <StringToSign> GET Wed, 11 May 2011 07:59:25 GMT /oss-example?acl </StringToSign> <OSSAccessKeyId> AKIAIVAKMSMOY7VOMRWQ </OSSAccessKeyId> </Error> 说明 OSS SDK已经实现签名,用户使用OSS SDK不需要关注签名问题。如果您想了解具体语言的签名实现,请参考OSS SDK的代码。OSS SDK签名实现的文件如下表: SDK 签名实现 Java SDK OSSRequestSigner.java Python SDK auth.py .Net SDK OssRequestSigner.cs PHP SDK OssClient.php C SDK oss_auth.c JavaScript SDK client.js Go SDK auth.go Ruby SDK util.rb iOS SDK OSSModel.m Android SDK OSSUtils.java 当您自己实现签名,访问OSS报 SignatureDoesNotMatch 错误时,请使用可视化签名工具确认签名并排除错误。 常见问题 Content-MD5的计算方法 Content-MD5的计算 以消息内容为"123456789"来说,计算这个字符串的Content-MD5 正确的计算方式: 标准中定义的算法简单点说就是: 1. 先计算MD5加密的二进制数组(128位)。 2. 再对这个二进制进行base64编码(而不是对32位字符串编码)。 以Python为例子: 正确计算的代码为: >>> import base64,hashlib >>> hash = hashlib.md5() >>> hash.update("0123456789") >>> base64.b64encode(hash.digest()) 'eB5eJF1ptWaXm4bijSPyxw==' 需要注意 正确的是:hash.digest(),计算出进制数组(128位) >>> hash.digest() 'x\x1e^$]i\xb5f\x97\x9b\x86\xe2\x8d#\xf2\xc7' 常见错误是直接对计算出的32位字符串编码进行base64编码。 例如,错误的是:hash.hexdigest(),计算得到可见的32位字符串编码 >>> hash.hexdigest() '781e5e245d69b566979b86e28d23f2c7' 错误的MD5值进行base64编码后的结果: >>> base64.b64encode(hash.hexdigest()) 'NzgxZTVlMjQ1ZDY5YjU2Njk3OWI4NmUyOGQyM2YyYzc='

2019-12-01 23:13:44 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档 用户可以在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-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错误。 构建CanonicalizedOSSHeaders的方法 所有以 x-oss- 为前缀的HTTP Header被称为CanonicalizedOSSHeaders。它的构建方法如下: 将所有以 x-oss- 为前缀的HTTP请求头的名字转换成 小写 。如X-OSS-Meta-Name: TaoBao转换成x-oss-meta-name: TaoBao。 如果请求是以STS获得的AccessKeyId和AccessKeySecret发送时,还需要将获得的security-token值,以 x-oss-security-token:security-token 的形式加入到签名字符串中。 将上一步得到的所有HTTP请求头按照名字的字典序进行升序排列。 删除请求头和内容之间分隔符两端出现的任何空格。如x-oss-meta-name: TaoBao转换成:x-oss-meta-name:TaoBao。 将每一个头和内容用 \n 分隔符分隔拼成最后的CanonicalizedOSSHeaders。 说明 CanonicalizedOSSHeaders可以为空,无需添加最后的 \n。 如果只有一个,则如 x-oss-meta-a\n,注意最后的\n。 如果有多个,则如 x-oss-meta-a:a\nx-oss-meta-b:b\nx-oss-meta-c:c\n, 注意最后的\n。 构建CanonicalizedResource的方法 用户发送请求中想访问的OSS目标资源被称为CanonicalizedResource。它的构建方法如下: 将CanonicalizedResource置成空字符串 ""; 放入要访问的OSS资源 /BucketName/ObjectName(无ObjectName则CanonicalizedResource为”/BucketName/“,如果同时也没有BucketName则为“/”) 如果请求的资源包括子资源(SubResource) ,那么将所有的子资源按照字典序,从小到大排列并以 & 为分隔符生成子资源字符串。在CanonicalizedResource字符串尾添加 ?和子资源字符串。此时的CanonicalizedResource如:/BucketName/ObjectName?acl&uploadId=UploadId 如果用户请求在指定了查询字符串(QueryString,也叫Http Request Parameters),那么将这些查询字符串及其请求值按照 字典序,从小到大排列,以 & 为分隔符,按参数添加到CanonicalizedResource中。此时的CanonicalizedResource如:/BucketName/ObjectName?acl&response-content-type=ContentType&uploadId=UploadId。 说明 OSS目前支持的子资源(sub-resource)包括:acl,uploads,location,cors,logging,website,referer,lifecycle,delete,append,tagging,objectMeta,uploadId,partNumber,security-token,position,img,style,styleName,replication,replicationProgress,replicationLocation,cname,bucketInfo,comp,qos,live,status,vod,startTime,endTime,symlink,x-oss-process,response-content-type,response-content-language,response-expires,response-cache-control,response-content-disposition,response-content-encoding等 子资源(sub-resource)有三种类型: 资源标识,如子资源中的acl,append,uploadId,symlink等,详见关于Bucket的操作和关于Object的操作。 指定返回Header字段,如 response-***,详见GetObject的Request Parameters。 文件(Object)处理方式,如 x-oss-process,用于文件的处理方式,如图片处理。 计算签名头规则 签名的字符串必须为 UTF-8 格式。含有中文字符的签名字符串必须先进行 UTF-8 编码,再与 AccessKeySecret计算最终签名。 签名的方法用RFC 2104中定义的HMAC-SHA1方法,其中Key为 AccessKeySecret` 。 Content-Type 和 Content-MD5 在请求中不是必须的,但是如果请求需要签名验证,空值的话以换行符 \n 代替。 在所有非HTTP标准定义的header中,只有以 x-oss- 开头的header,需要加入签名字符串;其他非HTTP标准header将被OSS忽略(如上例中的x-oss-magic是需要加入签名字符串的)。 以 x-oss- 开头的header在签名验证前需要符合以下规范: header的名字需要变成小写。 header按字典序自小到大排序。 分割header name和value的冒号前后不能有空格。 每个Header之后都有一个换行符“\n”,如果没有Header,CanonicalizedOSSHeaders就设置为空。 签名示例 假如AccessKeyId是”44CF9590006BF252F707”,AccessKeySecret是”OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV” 请求 签名字符串计算公式 签名字符串 PUT /nelson HTTP/1.0 Content-MD5: eB5eJF1ptWaXm4bijSPyxw== Content-Type: text/html Date: Thu, 17 Nov 2005 18:49:58 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com X-OSS-Meta-Author: foo@bar.com X-OSS-Magic: abracadabra Signature = base64(hmac-sha1(AccessKeySecret,VERB + “\n” + Content-MD5 + “\n”+ Content-Type + “\n” + Date + “\n” + CanonicalizedOSSHeaders+ CanonicalizedResource)) “PUT\n eB5eJF1ptWaXm4bijSPyxw==\n text/html\n Thu, 17 Nov 2005 18:49:58 GMT\n x-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n/oss-example/nels 可用以下方法计算签名(Signature): python示例代码: import base64 import hmac import sha h = hmac.new("OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV", "PUT\nODBGOERFMDMzQTczRUY3NUE3NzA5QzdFNUYzMDQxNEM=\ntext/html\nThu, 17 Nov 2005 18:49:58 GMT\nx-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n/oss-example/nelson", sha) Signature = base64.b64encode(h.digest()) print("Signature: %s" % Signature) 签名(Signature)计算结果应该为 26NBxoKdsyly4EDv6inkoDft/yA=,因为Authorization = “OSS “ + AccessKeyId + “:” + Signature所以最后Authorization为 “OSS 44CF9590006BF252F707:26NBxoKdsyly4EDv6inkoDft/yA=”然后加上Authorization头来组成最后需要发送的消息: PUT /nelson HTTP/1.0 Authorization:OSS 44CF9590006BF252F707:26NBxoKdsyly4EDv6inkoDft/yA= Content-Md5: eB5eJF1ptWaXm4bijSPyxw== Content-Type: text/html Date: Thu, 17 Nov 2005 18:49:58 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com X-OSS-Meta-Author: foo@bar.com X-OSS-Magic: abracadabra 细节分析 如果传入的AccessKeyId不存在或inactive,返回403 Forbidden。错误码:InvalidAccessKeyId。 若用户请求头中Authorization值的格式不对,返回400 Bad Request。错误码:InvalidArgument。 OSS所有的请求都必须使用HTTP 1.1协议规定的GMT时间格式。其中,日期的格式为:date1 = 2DIGIT SP month SP 4DIGIT; day month year (e.g., 02 Jun 1982)上述日期格式中,“天”所占位数都是“2 DIGIT”。因此,“Jun 2”、“2 Jun 1982”和“2-Jun-82”都是非法日期格式。 如果签名验证的时候,头中没有传入Date或者格式不正确,返回403 Forbidden错误。错误码:AccessDenied。 传入请求的时间必须在OSS服务器当前时间之后的15分钟以内,否则返回403 Forbidden。错误码:RequestTimeTooSkewed。 如果AccessKeyId是active的,但OSS判断用户的请求发生签名错误,则返回403 Forbidden,并在返回给用户的response中告诉用户正确的用于验证加密的签名字符串。用户可以根据OSS的response来检查自己的签名字符串是否正确。返回示例:<?xml version="1.0" ?> <Error> <Code> SignatureDoesNotMatch </Code> <Message> The request signature we calculated does not match the signature you provided. Check your key and signing method. </Message> <StringToSignBytes> 47 45 54 0a 0a 0a 57 65 64 2c 20 31 31 20 4d 61 79 20 32 30 31 31 20 30 37 3a 35 39 3a 32 35 20 47 4d 54 0a 2f 75 73 72 65 61 6c 74 65 73 74 3f 61 63 6c </StringToSignBytes> <RequestId> 1E446260FF9B10C2 </RequestId> <HostId> oss-cn-hangzhou.aliyuncs.com </HostId> <SignatureProvided> y5H7yzPsA/tP4+0tH1HHvPEwUv8= </SignatureProvided> <StringToSign> GET Wed, 11 May 2011 07:59:25 GMT /oss-example?acl </StringToSign> <OSSAccessKeyId> AKIAIVAKMSMOY7VOMRWQ </OSSAccessKeyId> </Error> 说明 OSS SDK已经实现签名,用户使用OSS SDK不需要关注签名问题。如果您想了解具体语言的签名实现,请参考OSS SDK的代码。OSS SDK签名实现的文件如下表: SDK 签名实现 Java SDK OSSRequestSigner.java Python SDK auth.py .Net SDK OssRequestSigner.cs PHP SDK OssClient.php C SDK oss_auth.c JavaScript SDK client.js Go SDK auth.go Ruby SDK util.rb iOS SDK OSSModel.m Android SDK OSSUtils.java 当您自己实现签名,访问OSS报 SignatureDoesNotMatch 错误时,请使用可视化签名工具确认签名并排除错误。 常见问题 Content-MD5的计算方法 Content-MD5的计算 以消息内容为"123456789"来说,计算这个字符串的Content-MD5 正确的计算方式: 标准中定义的算法简单点说就是: 1. 先计算MD5加密的二进制数组(128位)。 2. 再对这个二进制进行base64编码(而不是对32位字符串编码)。 以Python为例子: 正确计算的代码为: >>> import base64,hashlib >>> hash = hashlib.md5() >>> hash.update("0123456789") >>> base64.b64encode(hash.digest()) 'eB5eJF1ptWaXm4bijSPyxw==' 需要注意 正确的是:hash.digest(),计算出进制数组(128位) >>> hash.digest() 'x\x1e^$]i\xb5f\x97\x9b\x86\xe2\x8d#\xf2\xc7' 常见错误是直接对计算出的32位字符串编码进行base64编码。 例如,错误的是:hash.hexdigest(),计算得到可见的32位字符串编码 >>> hash.hexdigest() '781e5e245d69b566979b86e28d23f2c7' 错误的MD5值进行base64编码后的结果: >>> base64.b64encode(hash.hexdigest()) 'NzgxZTVlMjQ1ZDY5YjU2Njk3OWI4NmUyOGQyM2YyYzc='

2019-12-01 23:13:43 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档 用户可以在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-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错误。 构建CanonicalizedOSSHeaders的方法 所有以 x-oss- 为前缀的HTTP Header被称为CanonicalizedOSSHeaders。它的构建方法如下: 将所有以 x-oss- 为前缀的HTTP请求头的名字转换成 小写 。如X-OSS-Meta-Name: TaoBao转换成x-oss-meta-name: TaoBao。 如果请求是以STS获得的AccessKeyId和AccessKeySecret发送时,还需要将获得的security-token值,以 x-oss-security-token:security-token 的形式加入到签名字符串中。 将上一步得到的所有HTTP请求头按照名字的字典序进行升序排列。 删除请求头和内容之间分隔符两端出现的任何空格。如x-oss-meta-name: TaoBao转换成:x-oss-meta-name:TaoBao。 将每一个头和内容用 \n 分隔符分隔拼成最后的CanonicalizedOSSHeaders。 说明 CanonicalizedOSSHeaders可以为空,无需添加最后的 \n。 如果只有一个,则如 x-oss-meta-a\n,注意最后的\n。 如果有多个,则如 x-oss-meta-a:a\nx-oss-meta-b:b\nx-oss-meta-c:c\n, 注意最后的\n。 构建CanonicalizedResource的方法 用户发送请求中想访问的OSS目标资源被称为CanonicalizedResource。它的构建方法如下: 将CanonicalizedResource置成空字符串 ""; 放入要访问的OSS资源 /BucketName/ObjectName(无ObjectName则CanonicalizedResource为”/BucketName/“,如果同时也没有BucketName则为“/”) 如果请求的资源包括子资源(SubResource) ,那么将所有的子资源按照字典序,从小到大排列并以 & 为分隔符生成子资源字符串。在CanonicalizedResource字符串尾添加 ?和子资源字符串。此时的CanonicalizedResource如:/BucketName/ObjectName?acl&uploadId=UploadId 如果用户请求在指定了查询字符串(QueryString,也叫Http Request Parameters),那么将这些查询字符串及其请求值按照 字典序,从小到大排列,以 & 为分隔符,按参数添加到CanonicalizedResource中。此时的CanonicalizedResource如:/BucketName/ObjectName?acl&response-content-type=ContentType&uploadId=UploadId。 说明 OSS目前支持的子资源(sub-resource)包括:acl,uploads,location,cors,logging,website,referer,lifecycle,delete,append,tagging,objectMeta,uploadId,partNumber,security-token,position,img,style,styleName,replication,replicationProgress,replicationLocation,cname,bucketInfo,comp,qos,live,status,vod,startTime,endTime,symlink,x-oss-process,response-content-type,response-content-language,response-expires,response-cache-control,response-content-disposition,response-content-encoding等 子资源(sub-resource)有三种类型: 资源标识,如子资源中的acl,append,uploadId,symlink等,详见关于Bucket的操作和关于Object的操作。 指定返回Header字段,如 response-***,详见GetObject的Request Parameters。 文件(Object)处理方式,如 x-oss-process,用于文件的处理方式,如图片处理。 计算签名头规则 签名的字符串必须为 UTF-8 格式。含有中文字符的签名字符串必须先进行 UTF-8 编码,再与 AccessKeySecret计算最终签名。 签名的方法用RFC 2104中定义的HMAC-SHA1方法,其中Key为 AccessKeySecret` 。 Content-Type 和 Content-MD5 在请求中不是必须的,但是如果请求需要签名验证,空值的话以换行符 \n 代替。 在所有非HTTP标准定义的header中,只有以 x-oss- 开头的header,需要加入签名字符串;其他非HTTP标准header将被OSS忽略(如上例中的x-oss-magic是需要加入签名字符串的)。 以 x-oss- 开头的header在签名验证前需要符合以下规范: header的名字需要变成小写。 header按字典序自小到大排序。 分割header name和value的冒号前后不能有空格。 每个Header之后都有一个换行符“\n”,如果没有Header,CanonicalizedOSSHeaders就设置为空。 签名示例 假如AccessKeyId是”44CF9590006BF252F707”,AccessKeySecret是”OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV” 请求 签名字符串计算公式 签名字符串 PUT /nelson HTTP/1.0 Content-MD5: eB5eJF1ptWaXm4bijSPyxw== Content-Type: text/html Date: Thu, 17 Nov 2005 18:49:58 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com X-OSS-Meta-Author: foo@bar.com X-OSS-Magic: abracadabra Signature = base64(hmac-sha1(AccessKeySecret,VERB + “\n” + Content-MD5 + “\n”+ Content-Type + “\n” + Date + “\n” + CanonicalizedOSSHeaders+ CanonicalizedResource)) “PUT\n eB5eJF1ptWaXm4bijSPyxw==\n text/html\n Thu, 17 Nov 2005 18:49:58 GMT\n x-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n/oss-example/nels 可用以下方法计算签名(Signature): python示例代码: import base64 import hmac import sha h = hmac.new("OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV", "PUT\nODBGOERFMDMzQTczRUY3NUE3NzA5QzdFNUYzMDQxNEM=\ntext/html\nThu, 17 Nov 2005 18:49:58 GMT\nx-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n/oss-example/nelson", sha) Signature = base64.b64encode(h.digest()) print("Signature: %s" % Signature) 签名(Signature)计算结果应该为 26NBxoKdsyly4EDv6inkoDft/yA=,因为Authorization = “OSS “ + AccessKeyId + “:” + Signature所以最后Authorization为 “OSS 44CF9590006BF252F707:26NBxoKdsyly4EDv6inkoDft/yA=”然后加上Authorization头来组成最后需要发送的消息: PUT /nelson HTTP/1.0 Authorization:OSS 44CF9590006BF252F707:26NBxoKdsyly4EDv6inkoDft/yA= Content-Md5: eB5eJF1ptWaXm4bijSPyxw== Content-Type: text/html Date: Thu, 17 Nov 2005 18:49:58 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com X-OSS-Meta-Author: foo@bar.com X-OSS-Magic: abracadabra 细节分析 如果传入的AccessKeyId不存在或inactive,返回403 Forbidden。错误码:InvalidAccessKeyId。 若用户请求头中Authorization值的格式不对,返回400 Bad Request。错误码:InvalidArgument。 OSS所有的请求都必须使用HTTP 1.1协议规定的GMT时间格式。其中,日期的格式为:date1 = 2DIGIT SP month SP 4DIGIT; day month year (e.g., 02 Jun 1982)上述日期格式中,“天”所占位数都是“2 DIGIT”。因此,“Jun 2”、“2 Jun 1982”和“2-Jun-82”都是非法日期格式。 如果签名验证的时候,头中没有传入Date或者格式不正确,返回403 Forbidden错误。错误码:AccessDenied。 传入请求的时间必须在OSS服务器当前时间之后的15分钟以内,否则返回403 Forbidden。错误码:RequestTimeTooSkewed。 如果AccessKeyId是active的,但OSS判断用户的请求发生签名错误,则返回403 Forbidden,并在返回给用户的response中告诉用户正确的用于验证加密的签名字符串。用户可以根据OSS的response来检查自己的签名字符串是否正确。返回示例:<?xml version="1.0" ?> <Error> <Code> SignatureDoesNotMatch </Code> <Message> The request signature we calculated does not match the signature you provided. Check your key and signing method. </Message> <StringToSignBytes> 47 45 54 0a 0a 0a 57 65 64 2c 20 31 31 20 4d 61 79 20 32 30 31 31 20 30 37 3a 35 39 3a 32 35 20 47 4d 54 0a 2f 75 73 72 65 61 6c 74 65 73 74 3f 61 63 6c </StringToSignBytes> <RequestId> 1E446260FF9B10C2 </RequestId> <HostId> oss-cn-hangzhou.aliyuncs.com </HostId> <SignatureProvided> y5H7yzPsA/tP4+0tH1HHvPEwUv8= </SignatureProvided> <StringToSign> GET Wed, 11 May 2011 07:59:25 GMT /oss-example?acl </StringToSign> <OSSAccessKeyId> AKIAIVAKMSMOY7VOMRWQ </OSSAccessKeyId> </Error> 说明 OSS SDK已经实现签名,用户使用OSS SDK不需要关注签名问题。如果您想了解具体语言的签名实现,请参考OSS SDK的代码。OSS SDK签名实现的文件如下表: SDK 签名实现 Java SDK OSSRequestSigner.java Python SDK auth.py .Net SDK OssRequestSigner.cs PHP SDK OssClient.php C SDK oss_auth.c JavaScript SDK client.js Go SDK auth.go Ruby SDK util.rb iOS SDK OSSModel.m Android SDK OSSUtils.java 当您自己实现签名,访问OSS报 SignatureDoesNotMatch 错误时,请使用可视化签名工具确认签名并排除错误。 常见问题 Content-MD5的计算方法 Content-MD5的计算 以消息内容为"123456789"来说,计算这个字符串的Content-MD5 正确的计算方式: 标准中定义的算法简单点说就是: 1. 先计算MD5加密的二进制数组(128位)。 2. 再对这个二进制进行base64编码(而不是对32位字符串编码)。 以Python为例子: 正确计算的代码为: >>> import base64,hashlib >>> hash = hashlib.md5() >>> hash.update("0123456789") >>> base64.b64encode(hash.digest()) 'eB5eJF1ptWaXm4bijSPyxw==' 需要注意 正确的是:hash.digest(),计算出进制数组(128位) >>> hash.digest() 'x\x1e^$]i\xb5f\x97\x9b\x86\xe2\x8d#\xf2\xc7' 常见错误是直接对计算出的32位字符串编码进行base64编码。 例如,错误的是:hash.hexdigest(),计算得到可见的32位字符串编码 >>> hash.hexdigest() '781e5e245d69b566979b86e28d23f2c7' 错误的MD5值进行base64编码后的结果: >>> base64.b64encode(hash.hexdigest()) 'NzgxZTVlMjQ1ZDY5YjU2Njk3OWI4NmUyOGQyM2YyYzc='

2019-12-01 23:13:45 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档 用户可以在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-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错误。 构建CanonicalizedOSSHeaders的方法 所有以 x-oss- 为前缀的HTTP Header被称为CanonicalizedOSSHeaders。它的构建方法如下: 将所有以 x-oss- 为前缀的HTTP请求头的名字转换成 小写 。如X-OSS-Meta-Name: TaoBao转换成x-oss-meta-name: TaoBao。 如果请求是以STS获得的AccessKeyId和AccessKeySecret发送时,还需要将获得的security-token值,以 x-oss-security-token:security-token 的形式加入到签名字符串中。 将上一步得到的所有HTTP请求头按照名字的字典序进行升序排列。 删除请求头和内容之间分隔符两端出现的任何空格。如x-oss-meta-name: TaoBao转换成:x-oss-meta-name:TaoBao。 将每一个头和内容用 \n 分隔符分隔拼成最后的CanonicalizedOSSHeaders。 说明 CanonicalizedOSSHeaders可以为空,无需添加最后的 \n。 如果只有一个,则如 x-oss-meta-a\n,注意最后的\n。 如果有多个,则如 x-oss-meta-a:a\nx-oss-meta-b:b\nx-oss-meta-c:c\n, 注意最后的\n。 构建CanonicalizedResource的方法 用户发送请求中想访问的OSS目标资源被称为CanonicalizedResource。它的构建方法如下: 将CanonicalizedResource置成空字符串 ""; 放入要访问的OSS资源 /BucketName/ObjectName(无ObjectName则CanonicalizedResource为”/BucketName/“,如果同时也没有BucketName则为“/”) 如果请求的资源包括子资源(SubResource) ,那么将所有的子资源按照字典序,从小到大排列并以 & 为分隔符生成子资源字符串。在CanonicalizedResource字符串尾添加 ?和子资源字符串。此时的CanonicalizedResource如:/BucketName/ObjectName?acl&uploadId=UploadId 如果用户请求在指定了查询字符串(QueryString,也叫Http Request Parameters),那么将这些查询字符串及其请求值按照 字典序,从小到大排列,以 & 为分隔符,按参数添加到CanonicalizedResource中。此时的CanonicalizedResource如:/BucketName/ObjectName?acl&response-content-type=ContentType&uploadId=UploadId。 说明 OSS目前支持的子资源(sub-resource)包括:acl,uploads,location,cors,logging,website,referer,lifecycle,delete,append,tagging,objectMeta,uploadId,partNumber,security-token,position,img,style,styleName,replication,replicationProgress,replicationLocation,cname,bucketInfo,comp,qos,live,status,vod,startTime,endTime,symlink,x-oss-process,response-content-type,response-content-language,response-expires,response-cache-control,response-content-disposition,response-content-encoding等 子资源(sub-resource)有三种类型: 资源标识,如子资源中的acl,append,uploadId,symlink等,详见关于Bucket的操作和关于Object的操作。 指定返回Header字段,如 response-***,详见GetObject的Request Parameters。 文件(Object)处理方式,如 x-oss-process,用于文件的处理方式,如图片处理。 计算签名头规则 签名的字符串必须为 UTF-8 格式。含有中文字符的签名字符串必须先进行 UTF-8 编码,再与 AccessKeySecret计算最终签名。 签名的方法用RFC 2104中定义的HMAC-SHA1方法,其中Key为 AccessKeySecret` 。 Content-Type 和 Content-MD5 在请求中不是必须的,但是如果请求需要签名验证,空值的话以换行符 \n 代替。 在所有非HTTP标准定义的header中,只有以 x-oss- 开头的header,需要加入签名字符串;其他非HTTP标准header将被OSS忽略(如上例中的x-oss-magic是需要加入签名字符串的)。 以 x-oss- 开头的header在签名验证前需要符合以下规范: header的名字需要变成小写。 header按字典序自小到大排序。 分割header name和value的冒号前后不能有空格。 每个Header之后都有一个换行符“\n”,如果没有Header,CanonicalizedOSSHeaders就设置为空。 签名示例 假如AccessKeyId是”44CF9590006BF252F707”,AccessKeySecret是”OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV” 请求 签名字符串计算公式 签名字符串 PUT /nelson HTTP/1.0 Content-MD5: eB5eJF1ptWaXm4bijSPyxw== Content-Type: text/html Date: Thu, 17 Nov 2005 18:49:58 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com X-OSS-Meta-Author: foo@bar.com X-OSS-Magic: abracadabra Signature = base64(hmac-sha1(AccessKeySecret,VERB + “\n” + Content-MD5 + “\n”+ Content-Type + “\n” + Date + “\n” + CanonicalizedOSSHeaders+ CanonicalizedResource)) “PUT\n eB5eJF1ptWaXm4bijSPyxw==\n text/html\n Thu, 17 Nov 2005 18:49:58 GMT\n x-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n/oss-example/nels 可用以下方法计算签名(Signature): python示例代码: import base64 import hmac import sha h = hmac.new("OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV", "PUT\nODBGOERFMDMzQTczRUY3NUE3NzA5QzdFNUYzMDQxNEM=\ntext/html\nThu, 17 Nov 2005 18:49:58 GMT\nx-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n/oss-example/nelson", sha) Signature = base64.b64encode(h.digest()) print("Signature: %s" % Signature) 签名(Signature)计算结果应该为 26NBxoKdsyly4EDv6inkoDft/yA=,因为Authorization = “OSS “ + AccessKeyId + “:” + Signature所以最后Authorization为 “OSS 44CF9590006BF252F707:26NBxoKdsyly4EDv6inkoDft/yA=”然后加上Authorization头来组成最后需要发送的消息: PUT /nelson HTTP/1.0 Authorization:OSS 44CF9590006BF252F707:26NBxoKdsyly4EDv6inkoDft/yA= Content-Md5: eB5eJF1ptWaXm4bijSPyxw== Content-Type: text/html Date: Thu, 17 Nov 2005 18:49:58 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com X-OSS-Meta-Author: foo@bar.com X-OSS-Magic: abracadabra 细节分析 如果传入的AccessKeyId不存在或inactive,返回403 Forbidden。错误码:InvalidAccessKeyId。 若用户请求头中Authorization值的格式不对,返回400 Bad Request。错误码:InvalidArgument。 OSS所有的请求都必须使用HTTP 1.1协议规定的GMT时间格式。其中,日期的格式为:date1 = 2DIGIT SP month SP 4DIGIT; day month year (e.g., 02 Jun 1982)上述日期格式中,“天”所占位数都是“2 DIGIT”。因此,“Jun 2”、“2 Jun 1982”和“2-Jun-82”都是非法日期格式。 如果签名验证的时候,头中没有传入Date或者格式不正确,返回403 Forbidden错误。错误码:AccessDenied。 传入请求的时间必须在OSS服务器当前时间之后的15分钟以内,否则返回403 Forbidden。错误码:RequestTimeTooSkewed。 如果AccessKeyId是active的,但OSS判断用户的请求发生签名错误,则返回403 Forbidden,并在返回给用户的response中告诉用户正确的用于验证加密的签名字符串。用户可以根据OSS的response来检查自己的签名字符串是否正确。返回示例:<?xml version="1.0" ?> <Error> <Code> SignatureDoesNotMatch </Code> <Message> The request signature we calculated does not match the signature you provided. Check your key and signing method. </Message> <StringToSignBytes> 47 45 54 0a 0a 0a 57 65 64 2c 20 31 31 20 4d 61 79 20 32 30 31 31 20 30 37 3a 35 39 3a 32 35 20 47 4d 54 0a 2f 75 73 72 65 61 6c 74 65 73 74 3f 61 63 6c </StringToSignBytes> <RequestId> 1E446260FF9B10C2 </RequestId> <HostId> oss-cn-hangzhou.aliyuncs.com </HostId> <SignatureProvided> y5H7yzPsA/tP4+0tH1HHvPEwUv8= </SignatureProvided> <StringToSign> GET Wed, 11 May 2011 07:59:25 GMT /oss-example?acl </StringToSign> <OSSAccessKeyId> AKIAIVAKMSMOY7VOMRWQ </OSSAccessKeyId> </Error> 说明 OSS SDK已经实现签名,用户使用OSS SDK不需要关注签名问题。如果您想了解具体语言的签名实现,请参考OSS SDK的代码。OSS SDK签名实现的文件如下表: SDK 签名实现 Java SDK OSSRequestSigner.java Python SDK auth.py .Net SDK OssRequestSigner.cs PHP SDK OssClient.php C SDK oss_auth.c JavaScript SDK client.js Go SDK auth.go Ruby SDK util.rb iOS SDK OSSModel.m Android SDK OSSUtils.java 当您自己实现签名,访问OSS报 SignatureDoesNotMatch 错误时,请使用可视化签名工具确认签名并排除错误。 常见问题 Content-MD5的计算方法 Content-MD5的计算 以消息内容为"123456789"来说,计算这个字符串的Content-MD5 正确的计算方式: 标准中定义的算法简单点说就是: 1. 先计算MD5加密的二进制数组(128位)。 2. 再对这个二进制进行base64编码(而不是对32位字符串编码)。 以Python为例子: 正确计算的代码为: >>> import base64,hashlib >>> hash = hashlib.md5() >>> hash.update("0123456789") >>> base64.b64encode(hash.digest()) 'eB5eJF1ptWaXm4bijSPyxw==' 需要注意 正确的是:hash.digest(),计算出进制数组(128位) >>> hash.digest() 'x\x1e^$]i\xb5f\x97\x9b\x86\xe2\x8d#\xf2\xc7' 常见错误是直接对计算出的32位字符串编码进行base64编码。 例如,错误的是:hash.hexdigest(),计算得到可见的32位字符串编码 >>> hash.hexdigest() '781e5e245d69b566979b86e28d23f2c7' 错误的MD5值进行base64编码后的结果: >>> base64.b64encode(hash.hexdigest()) 'NzgxZTVlMjQ1ZDY5YjU2Njk3OWI4NmUyOGQyM2YyYzc='

2019-12-01 23:13:43 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档 用户可以在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-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错误。 构建CanonicalizedOSSHeaders的方法 所有以 x-oss- 为前缀的HTTP Header被称为CanonicalizedOSSHeaders。它的构建方法如下: 将所有以 x-oss- 为前缀的HTTP请求头的名字转换成 小写 。如X-OSS-Meta-Name: TaoBao转换成x-oss-meta-name: TaoBao。 如果请求是以STS获得的AccessKeyId和AccessKeySecret发送时,还需要将获得的security-token值,以 x-oss-security-token:security-token 的形式加入到签名字符串中。 将上一步得到的所有HTTP请求头按照名字的字典序进行升序排列。 删除请求头和内容之间分隔符两端出现的任何空格。如x-oss-meta-name: TaoBao转换成:x-oss-meta-name:TaoBao。 将每一个头和内容用 \n 分隔符分隔拼成最后的CanonicalizedOSSHeaders。 说明 CanonicalizedOSSHeaders可以为空,无需添加最后的 \n。 如果只有一个,则如 x-oss-meta-a\n,注意最后的\n。 如果有多个,则如 x-oss-meta-a:a\nx-oss-meta-b:b\nx-oss-meta-c:c\n, 注意最后的\n。 构建CanonicalizedResource的方法 用户发送请求中想访问的OSS目标资源被称为CanonicalizedResource。它的构建方法如下: 将CanonicalizedResource置成空字符串 ""; 放入要访问的OSS资源 /BucketName/ObjectName(无ObjectName则CanonicalizedResource为”/BucketName/“,如果同时也没有BucketName则为“/”) 如果请求的资源包括子资源(SubResource) ,那么将所有的子资源按照字典序,从小到大排列并以 & 为分隔符生成子资源字符串。在CanonicalizedResource字符串尾添加 ?和子资源字符串。此时的CanonicalizedResource如:/BucketName/ObjectName?acl&uploadId=UploadId 如果用户请求在指定了查询字符串(QueryString,也叫Http Request Parameters),那么将这些查询字符串及其请求值按照 字典序,从小到大排列,以 & 为分隔符,按参数添加到CanonicalizedResource中。此时的CanonicalizedResource如:/BucketName/ObjectName?acl&response-content-type=ContentType&uploadId=UploadId。 说明 OSS目前支持的子资源(sub-resource)包括:acl,uploads,location,cors,logging,website,referer,lifecycle,delete,append,tagging,objectMeta,uploadId,partNumber,security-token,position,img,style,styleName,replication,replicationProgress,replicationLocation,cname,bucketInfo,comp,qos,live,status,vod,startTime,endTime,symlink,x-oss-process,response-content-type,response-content-language,response-expires,response-cache-control,response-content-disposition,response-content-encoding等 子资源(sub-resource)有三种类型: 资源标识,如子资源中的acl,append,uploadId,symlink等,详见关于Bucket的操作和关于Object的操作。 指定返回Header字段,如 response-***,详见GetObject的Request Parameters。 文件(Object)处理方式,如 x-oss-process,用于文件的处理方式,如图片处理。 计算签名头规则 签名的字符串必须为 UTF-8 格式。含有中文字符的签名字符串必须先进行 UTF-8 编码,再与 AccessKeySecret计算最终签名。 签名的方法用RFC 2104中定义的HMAC-SHA1方法,其中Key为 AccessKeySecret` 。 Content-Type 和 Content-MD5 在请求中不是必须的,但是如果请求需要签名验证,空值的话以换行符 \n 代替。 在所有非HTTP标准定义的header中,只有以 x-oss- 开头的header,需要加入签名字符串;其他非HTTP标准header将被OSS忽略(如上例中的x-oss-magic是需要加入签名字符串的)。 以 x-oss- 开头的header在签名验证前需要符合以下规范: header的名字需要变成小写。 header按字典序自小到大排序。 分割header name和value的冒号前后不能有空格。 每个Header之后都有一个换行符“\n”,如果没有Header,CanonicalizedOSSHeaders就设置为空。 签名示例 假如AccessKeyId是”44CF9590006BF252F707”,AccessKeySecret是”OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV” 请求 签名字符串计算公式 签名字符串 PUT /nelson HTTP/1.0 Content-MD5: eB5eJF1ptWaXm4bijSPyxw== Content-Type: text/html Date: Thu, 17 Nov 2005 18:49:58 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com X-OSS-Meta-Author: foo@bar.com X-OSS-Magic: abracadabra Signature = base64(hmac-sha1(AccessKeySecret,VERB + “\n” + Content-MD5 + “\n”+ Content-Type + “\n” + Date + “\n” + CanonicalizedOSSHeaders+ CanonicalizedResource)) “PUT\n eB5eJF1ptWaXm4bijSPyxw==\n text/html\n Thu, 17 Nov 2005 18:49:58 GMT\n x-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n/oss-example/nels 可用以下方法计算签名(Signature): python示例代码: import base64 import hmac import sha h = hmac.new("OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV", "PUT\nODBGOERFMDMzQTczRUY3NUE3NzA5QzdFNUYzMDQxNEM=\ntext/html\nThu, 17 Nov 2005 18:49:58 GMT\nx-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n/oss-example/nelson", sha) Signature = base64.b64encode(h.digest()) print("Signature: %s" % Signature) 签名(Signature)计算结果应该为 26NBxoKdsyly4EDv6inkoDft/yA=,因为Authorization = “OSS “ + AccessKeyId + “:” + Signature所以最后Authorization为 “OSS 44CF9590006BF252F707:26NBxoKdsyly4EDv6inkoDft/yA=”然后加上Authorization头来组成最后需要发送的消息: PUT /nelson HTTP/1.0 Authorization:OSS 44CF9590006BF252F707:26NBxoKdsyly4EDv6inkoDft/yA= Content-Md5: eB5eJF1ptWaXm4bijSPyxw== Content-Type: text/html Date: Thu, 17 Nov 2005 18:49:58 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com X-OSS-Meta-Author: foo@bar.com X-OSS-Magic: abracadabra 细节分析 如果传入的AccessKeyId不存在或inactive,返回403 Forbidden。错误码:InvalidAccessKeyId。 若用户请求头中Authorization值的格式不对,返回400 Bad Request。错误码:InvalidArgument。 OSS所有的请求都必须使用HTTP 1.1协议规定的GMT时间格式。其中,日期的格式为:date1 = 2DIGIT SP month SP 4DIGIT; day month year (e.g., 02 Jun 1982)上述日期格式中,“天”所占位数都是“2 DIGIT”。因此,“Jun 2”、“2 Jun 1982”和“2-Jun-82”都是非法日期格式。 如果签名验证的时候,头中没有传入Date或者格式不正确,返回403 Forbidden错误。错误码:AccessDenied。 传入请求的时间必须在OSS服务器当前时间之后的15分钟以内,否则返回403 Forbidden。错误码:RequestTimeTooSkewed。 如果AccessKeyId是active的,但OSS判断用户的请求发生签名错误,则返回403 Forbidden,并在返回给用户的response中告诉用户正确的用于验证加密的签名字符串。用户可以根据OSS的response来检查自己的签名字符串是否正确。返回示例:<?xml version="1.0" ?> <Error> <Code> SignatureDoesNotMatch </Code> <Message> The request signature we calculated does not match the signature you provided. Check your key and signing method. </Message> <StringToSignBytes> 47 45 54 0a 0a 0a 57 65 64 2c 20 31 31 20 4d 61 79 20 32 30 31 31 20 30 37 3a 35 39 3a 32 35 20 47 4d 54 0a 2f 75 73 72 65 61 6c 74 65 73 74 3f 61 63 6c </StringToSignBytes> <RequestId> 1E446260FF9B10C2 </RequestId> <HostId> oss-cn-hangzhou.aliyuncs.com </HostId> <SignatureProvided> y5H7yzPsA/tP4+0tH1HHvPEwUv8= </SignatureProvided> <StringToSign> GET Wed, 11 May 2011 07:59:25 GMT /oss-example?acl </StringToSign> <OSSAccessKeyId> AKIAIVAKMSMOY7VOMRWQ </OSSAccessKeyId> </Error> 说明 OSS SDK已经实现签名,用户使用OSS SDK不需要关注签名问题。如果您想了解具体语言的签名实现,请参考OSS SDK的代码。OSS SDK签名实现的文件如下表: SDK 签名实现 Java SDK OSSRequestSigner.java Python SDK auth.py .Net SDK OssRequestSigner.cs PHP SDK OssClient.php C SDK oss_auth.c JavaScript SDK client.js Go SDK auth.go Ruby SDK util.rb iOS SDK OSSModel.m Android SDK OSSUtils.java 当您自己实现签名,访问OSS报 SignatureDoesNotMatch 错误时,请使用可视化签名工具确认签名并排除错误。 常见问题 Content-MD5的计算方法 Content-MD5的计算 以消息内容为"123456789"来说,计算这个字符串的Content-MD5 正确的计算方式: 标准中定义的算法简单点说就是: 1. 先计算MD5加密的二进制数组(128位)。 2. 再对这个二进制进行base64编码(而不是对32位字符串编码)。 以Python为例子: 正确计算的代码为: >>> import base64,hashlib >>> hash = hashlib.md5() >>> hash.update("0123456789") >>> base64.b64encode(hash.digest()) 'eB5eJF1ptWaXm4bijSPyxw==' 需要注意 正确的是:hash.digest(),计算出进制数组(128位) >>> hash.digest() 'x\x1e^$]i\xb5f\x97\x9b\x86\xe2\x8d#\xf2\xc7' 常见错误是直接对计算出的32位字符串编码进行base64编码。 例如,错误的是:hash.hexdigest(),计算得到可见的32位字符串编码 >>> hash.hexdigest() '781e5e245d69b566979b86e28d23f2c7' 错误的MD5值进行base64编码后的结果: >>> base64.b64encode(hash.hexdigest()) 'NzgxZTVlMjQ1ZDY5YjU2Njk3OWI4NmUyOGQyM2YyYzc='

2019-12-01 23:13:45 0 浏览量 回答数 0

问题

python+selenium+firefox ActionChains鼠标事件报错 ?报错

爱吃鱼的程序员 2020-06-23 01:27:14 0 浏览量 回答数 1

问题

如何在python中将参数滑块添加到微分方程图?

一码平川MACHEL 2019-12-01 19:32:10 389 浏览量 回答数 1

回答

一、文件的打开和创建 ? 12345 f = open('/tmp/test.txt')f.read()'hello python!nhello world!n'f 二、文件的读取步骤:打开 -- 读取 -- 关闭 ? 1234 f = open('/tmp/test.txt')f.read() 'hello python!nhello world!n' f.close() 读取数据是后期数据处理的必要步骤。.txt是广泛使用的数据文件格式。一些.csv, .xlsx等文件可以转换为.txt 文件进行读取。我常使用的是Python自带的I/O接口,将数据读取进来存放在list中,然后再用numpy科学计算包将list的数据转换为array格式,从而可以像MATLAB一样进行科学计算。 下面是一段常用的读取txt文件代码,可以用在大多数的txt文件读取中 ? 12345678910111213141516 filename = 'array_reflection_2D_TM_vertical_normE_center.txt' # txt文件和当前脚本在同一目录下,所以不用写具体路径pos = []Efield = []with open(filename, 'r') as file_to_read: while True: lines = file_to_read.readline() # 整行读取数据 if not lines: break pass p_tmp, E_tmp = [float(i) for i in lines.split()] # 将整行数据分割处理,如果分割符是空格,括号里就不用传入参数,如果是逗号, 则传入‘,'字符。 pos.append(p_tmp) # 添加新读取的数据 Efield.append(E_tmp) pass pos = np.array(pos) # 将数据从list类型转换为array类型。 Efield = np.array(Efield) pass 例如下面是将要读入的txt文件 2016626171647895.png (429×301) 经过读取后,在Enthought Canopy的variable window查看读入的数据, 左侧为pos,右侧为Efield。 2016626171713978.png (148×277)2016626171743777.png (147×280) 三、文件写入(慎重,小心别清空原本的文件)步骤:打开 -- 写入 -- (保存)关闭 直接的写入数据是不行的,因为默认打开的是'r' 只读模式 ? 123456 f.write('hello boy')Traceback (most recent call last): File "", line 1, in IOError: File not open for writing f 应该先指定可写的模式 ? 12 f1 = open('/tmp/test.txt','w')f1.write('hello boy!') 但此时数据只写到了缓存中,并未保存到文件,而且从下面的输出可以看到,原先里面的配置被清空了 ? 12 [root@node1 ~]# cat /tmp/test.txt[root@node1 ~]# 关闭这个文件即可将缓存中的数据写入到文件中 ? 123 f1.close() [root@node1 ~]# cat /tmp/test.txt[root@node1 ~]# hello boy! 注意:这一步需要相当慎重,因为如果编辑的文件存在的话,这一步操作会先清空这个文件再重新写入。那么如果不要清空文件再写入该如何做呢? 使用r+ 模式不会先清空,但是会替换掉原先的文件,如下面的例子:hello boy! 被替换成hello aay! ? 12345 f2 = open('/tmp/test.txt','r+')f2.write('nhello aa!')f2.close() [root@node1 python]# cat /tmp/test.txthello aay! 如何实现不替换? ? 12345678 f2 = open('/tmp/test.txt','r+')f2.read() 'hello girl!' f2.write('nhello boy!')f2.close() [root@node1 python]# cat /tmp/test.txthello girl!hello boy! 可以看到,如果在写之前先读取一下文件,再进行写入,则写入的数据会添加到文件末尾而不会替换掉原先的文件。这是因为指针引起的,r+ 模式的指针默认是在文件的开头,如果直接写入,则会覆盖源文件,通过read() 读取文件后,指针会移到文件的末尾,再写入数据就不会有问题了。这里也可以使用a 模式 ? 12345678 f = open('/tmp/test.txt','a')f.write('nhello man!')f.close() [root@node1 python]# cat /tmp/test.txthello girl!hello boy!hello man! 关于其他模式的介绍,见下表: 2016626170852899.png (713×317) 文件对象的方法:f.readline() 逐行读取数据 方法一: ? 123456789 f = open('/tmp/test.txt')f.readline() 'hello girl!n' f.readline() 'hello boy!n' f.readline() 'hello man!' f.readline() '' 方法二: ? 123456789101112 for i in open('/tmp/test.txt'): ... print i...hello girl!hello boy!hello man!f.readlines() 将文件内容以列表的形式存放 f = open('/tmp/test.txt')f.readlines() ['hello girl!n', 'hello boy!n', 'hello man!'] f.close() f.next() 逐行读取数据,和f.readline() 相似,唯一不同的是,f.readline() 读取到最后如果没有数据会返回空,而f.next() 没读取到数据则会报错 ? 12345678910111213141516 f = open('/tmp/test.txt')f.readlines() ['hello girl!n', 'hello boy!n', 'hello man!'] f.close() f = open('/tmp/test.txt')f.next() 'hello girl!n' f.next() 'hello boy!n' f.next() 'hello man!' f.next() Traceback (most recent call last):File "", line 1, in StopIteration f.writelines() 多行写入 ? 1234567891011 l = ['nhello dear!','nhello son!','nhello baby!n']f = open('/tmp/test.txt','a')f.writelines(l)f.close() [root@node1 python]# cat /tmp/test.txthello girl!hello boy!hello man!hello dear!hello son!hello baby! f.seek(偏移量,选项) ? 12345678910111213141516 f = open('/tmp/test.txt','r+')f.readline() 'hello girl!n' f.readline() 'hello boy!n' f.readline() 'hello man!n' f.readline() ' ' f.close()f = open('/tmp/test.txt','r+')f.read() 'hello girl!nhello boy!nhello man!n' f.readline() '' f.close() 这个例子可以充分的解释前面使用r+这个模式的时候,为什么需要执行f.read()之后才能正常插入f.seek(偏移量,选项)(1)选项=0,表示将文件指针指向从文件头部到“偏移量”字节处 (2)选项=1,表示将文件指针指向从文件的当前位置,向后移动“偏移量”字节 (3)选项=2,表示将文件指针指向从文件的尾部,向前移动“偏移量”字节 偏移量:正数表示向右偏移,负数表示向左偏移 ? 12345678910111213 f = open('/tmp/test.txt','r+')f.seek(0,2)f.readline() '' f.seek(0,0)f.readline() 'hello girl!n' f.readline() 'hello boy!n' f.readline() 'hello man!n' f.readline() '' f.flush() 将修改写入到文件中(无需关闭文件) ? 12 f.write('hello python!')f.flush() ? 1 [root@node1 python]# cat /tmp/test.txt ? 1234 hello girl!hello boy!hello man!hello python! f.tell() 获取指针位置 ? 123456789 f = open('/tmp/test.txt')f.readline() 'hello girl!n' f.tell() 12 f.readline() 'hello boy!n' f.tell() 23 四、内容查找和替换1、内容查找实例:统计文件中hello个数 思路:打开文件,遍历文件内容,通过正则表达式匹配关键字,统计匹配个数。 ? 1 [root@node1 ~]# cat /tmp/test.txt ? 1234 hello girl!hello boy!hello man!hello python! 脚本如下: 方法一: ? 12345678910 !/usr/bin/python import ref = open('/tmp/test.txt')source = f.read()f.close()r = r'hello's = len(re.findall(r,source))print s[root@node1 python]# python count.py4 方法二: ? 123456789101112 !/usr/bin/python import refp = file("/tmp/test.txt",'r')count = 0for s in fp.readlines():li = re.findall("hello",s)if len(li)>0:count = count + len(li)print "Search",count, "hello"fp.close()[root@node1 python]# python count1.pySearch 4 hello 2、替换实例:把test.txt 中的hello全部换为"hi",并把结果保存到myhello.txt中。 ? 1234567891011121314 !/usr/bin/python import ref1 = open('/tmp/test.txt')f2 = open('/tmp/myhello.txt','r+')for s in f1.readlines():f2.write(s.replace('hello','hi'))f1.close()f2.close()[root@node1 python]# touch /tmp/myhello.txt[root@node1 ~]# cat /tmp/myhello.txthi girl!hi boy!hi man!hi python! 实例:读取文件test.txt内容,去除空行和注释行后,以行为单位进行排序,并将结果输出为result.txt。test.txt 的内容如下所示: ? 12345678910111213141516171819 some words Sometimes in life,You find a special friend;Someone who changes your life just by being part of it.Someone who makes you laugh until you can't stop;Someone who makes you believe that there really is good in the world.Someone who convinces you that there really is an unlocked door just waiting for you to open it.This is Forever Friendship.when you're down,and the world seems dark and empty,Your forever friend lifts you up in spirits and makes that dark and empty worldsuddenly seem bright and full.Your forever friend gets you through the hard times,the sad times,and the confused times.If you turn and walk away,Your forever friend follows,If you lose you way,Your forever friend guides you and cheers you on.Your forever friend holds your hand and tells you that everything is going to be okay. 脚本如下: ? 12345678910 f = open('cdays-4-test.txt')result = list()for line in f.readlines(): # 逐行读取数据line = line.strip() #去掉每行头尾空白if not len(line) or line.startswith('#'): # 判断是否是空行或注释行continue #是的话,跳过不处理result.append(line) #保存result.sort() #排序结果print resultopen('cdays-4-result.txt','w').write('%s' % 'n'.join(result))

xuning715 2019-12-02 01:10:18 0 浏览量 回答数 0

回答

一、解释 递归:在调用一个函数的过程中,直接或间接地调用了函数本身这个就叫递归 注:Python在递归中没有像别的语言对递归进行优化,所以他的每一次调用都会基于上一次的调用进行,并且他设置了最大的递归数量防止递归外溢 二、实例 直接调用自己: def func(): print('from func') func() func()复制代码 间接调用自己 def foo(): print('from foo') bar() def bar(): print('from bar') foo() foo()复制代码复制代码 递归的实现: def age(n): if n == 1: return 18 return age(n-1)+2 print(age(5)) age(5)=age(4)+2 第一次进入 age(4)=age(3)+2 第二次进入 age(3)=age(2)+2 第三次进入 age(2)=age(1)+2 第四次进入 age(1)=18 第五次进入,最后判断终止条件 age(n)=age(n-1)+2 #n>1 递归终止条件 age(1)=18 #n=1 等于终止条件 复制代码三、递归的回溯与递推 递推:像上边递归实现所拆解,递归每一次都是基于上一次进行下一次的执行,这叫递推 回溯:则是在遇到终止条件,则从最后往回返一级一级的把值返回来,这叫回溯 复制代码 实例 l =[1, 2, [3, [4, 5, 6, [7, 8, [9, 10, [11, 12, 13, [14, 15,[16,[17,]],19]]]]]]] def search(l): for item in l: if type(item) is list: search(item) else: print(item) search(l) 递归算法 1、递归的定义 递归就是子程序(或函数)直接调用自己或通过一系列调用语句间接调用自己,是一种描述问题和解决问题的基本方法。 递归常与分治思想同时使用,能产生许多高校的算法。递归常用来解决结构相似的问题。所谓结构相似,是指构成原问题的子问题与原问题在结构上相似,可以用类似的方法解决。具体地,整个问题的解决,可以分为两部分:第一部分是一些特殊情况,有直接的解法;第二部分与原问题相似,但比原问题的规模小,并且依赖第一部分的结果。。实际上,递归是把一个不能或不好解决的大问题转化成一个或几个小问题,再把这些小问题进一步分解成更小的小问题,直至每个小问题都可以直接解决。因此,递归有两个基本要素: (1) 边界条件:确定递归到何时终止,也称为递归出口。 (2) 递归模式:大问题是如何分解为小问题的,也称为递归体。 递归函数只有具备了这两个要素,才能在有限次计算后得出结果。 2、递归算法实例 2.1求一个整数n的阶乘 阶乘的定义如下图: 图1 根据阶乘的递归定义,很容易就能写出求阶乘的递归算法。 def factorial(n) : if n == 1 : return 1 #递归结束 return n * factorial(n - 1) #问题规模减1,递归调用123452.2汉诺塔 汉诺塔问题是递归函数的经典应用,它来自一个古老传说:在世界刚被创建的时候有一座钻石宝塔A,其上有64个金蝶。所有碟子按从大到小的次序从塔底堆放至塔顶。紧挨着这座塔有另外两个钻石宝塔B和C。从世界创始之日起,波罗门的牧师就一直在试图把塔A上的碟子移动到C上去,其间借助于塔B的帮助。每次只能移动一个碟子,任何时候都不能把一个碟子放在比它小的碟子上面。当牧师们完成这个任务时,世界末日也就到了。 对于汉诺塔问题的求解,可以通过以下3步实现: (1)将塔A上的n -1个碟子借助C塔先移动到B塔上; (2)把塔A上剩下的一个碟子移动到塔C上; (3)将n - 1个碟子从B塔借助塔A移动到塔C上。 很显然,这是一个递归求解的过程,假设碟子数n=3时,汉诺塔问题的求解过程如下图所示: 图2 汉诺塔的递归算法(Python实现): def Hanoi(n, A, B, C) : if (n == 1) : move(A, c) #表示只有一个碟子时,直接从A塔移动到C塔 else : Hanoi(n - 1, A, C, B) #将剩下的A塔上的n-1借助C塔移动到B塔 move(A, C) #将A上最后一个直接移动到C塔上 Hanoi(n - 1, B, A, C) #将B塔上的n-1个碟子借助A塔移动到C塔 12345678递归函数的运行轨迹 借助汉诺塔这个实例,来讲解一下递归函数的运行轨迹。在递归函数中,调用函数和被调用函数都是同一个函数,需要注意的是函数的调用层次,如果把调用递归函数的主函数称为第0层,进入函数后,首次递归调用自身称为第1层调用;从第i层递归调用自身称为第i+1层。反之退出i+1层调用应该返回第i层。下图是n=3时汉诺塔算法的运行轨迹,有向弧上的数字表示递归调用和返回的执行顺序。 图3 汉诺塔的递归算法代码实现: coding=utf-8 i = 1def move(n, mfrom, mto) : global i print "第%d步:将%d号盘子从%s -> %s" %(i, n, mfrom, mto) i += 1 def hanoi(n, A, B, C) : if n == 1 : move(1, A, C) else : hanoi(n - 1, A, C, B) move(n, A, C) hanoi(n - 1, B, A, C) 程序入口 try : n = int(raw_input("please input a integer :")) print "移动步骤如下:" hanoi(n, 'A', 'B', 'C')except ValueError: print "please input a integer n(n > 0)!" 123456789101112131415161718192021222324执行结果: 结果 2.3 斐波拉契数列 斐波拉契数列,是这样的一个数列:0、1、1、2、3、5、8、13、21、……。 斐波拉契数列的核心思想是: 从第三项起,每一项都等于前两项的和,即F(N) = F(N - 1) + F(N - 2) (N >= 2) 并且规定F(0) = 0,F(1) = 1 要求:利用递归算法获得指定项的斐波拉契数列。 !/usr/bin/python coding=utf-8 def fib_list(n) : if n == 1 or n == 2 : return 1 else : m = fib_list(n - 1) + fib_list(n - 2) return m print "请输入要打印的斐波拉契数列项数n的值*"try : n = int(raw_input("enter:"))except ValueError : print "请输入一个整数!" exit()list2 = [0]tmp = 1while(tmp <= n): list2.append(fib_list(tmp)) tmp += 1print list2

xuning715 2019-12-02 01:10:16 0 浏览量 回答数 0

回答

转义只发生在代码字面量转换为python内部对象的过程中,已经是字符串了,则不会再次转义。例如:a = r'd:\new\red\t.txt'c = r'\\'.join(a.split("\\"))d = a.replace('\\', '/').strip()e = '/save' + d[2:]print(e)

xwaby 2019-12-02 01:32:19 0 浏览量 回答数 0

问题

使用带有--py文件的.zip文件(使用zipfile包在python中创建)导入模块时出现问题

小六码奴 2019-12-01 19:38:44 612 浏览量 回答数 1

回答

学习Python的人都知道数组是最常用的的数据类型,为了保证程序的正确性,需要调试程序。 因此,需要在程序中控制台中打印数组的全部元素,如果数组的容量较小,例如 只含有10个元素,采用print命令或print函数可以答应出数组中的每个元素; 如果数组的容量过大,只能打印出数组的部分元素,打印结果只包含开始部分元素和结尾部分元素,中间元素省略。省略的部分不利于程序的调试; 因此,为了方便调试程序,需要将数组中的元素全部打印出来。 少量元素情况 ? 1234 打印数组中的元素 import numpy as npa = np.array(6)print a 程序结果为: ? 1 [0 1 2 3 4 5] 大量元素情况 可以采用 set_printoptions(threshold='nan') ? 1234 import numpy as npnp.set_printoptions(threshold=np.NaN)print np.arange(100)print np.arange(100).reshape(10, 10) 结果为: [ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99] [[ 0 1 2 3 4 5 6 7 8 9] [10 11 12 13 14 15 16 17 18 19] [20 21 22 23 24 25 26 27 28 29] [30 31 32 33 34 35 36 37 38 39] [40 41 42 43 44 45 46 47 48 49] [50 51 52 53 54 55 56 57 58 59] [60 61 62 63 64 65 66 67 68 69] [70 71 72 73 74 75 76 77 78 79] [80 81 82 83 84 85 86 87 88 89] [90 91 92 93 94 95 96 97 98 99]] 当array里面的存放的数据维度过大时,在控制台会出现不能将array完全输出的情况,中间部分的结果会用省略号打印出来。这时就需要用到numpy里面的set_printoptions()方法 我们来看一下 set_printoptions 方法的简单说明 ? 12345678 set_printoptions(precision=None, threshold=None, edgeitems=None, linewidth=None, suppress=None, nanstr=None, infstr=None, formatter=None) precision:输出结果保留精度的位数 threshold:array数量的个数在小于threshold的时候不会被折叠 edgeitems:在array已经被折叠后,开头和结尾都会显示edgeitems个数 formatter:这个很有意思,像python3里面str.format(),就是可以对你的输出进行自定义的格式化 举例: precision: ? 123 np.set_printoptions(precision=4)print(np.array([1.23456789])) [ 1.2346] # 最后进位了 threshold: ? 123456 np.set_printoptions(threshold=10)print(np.arange(1, 11, 1)) # np.arange(1, 11, 1)生成出来是[1-10],10个数 [ 1 2 3 4 5 6 7 8 9 10] np.set_printoptions(threshold=9)print(np.arange(1, 11, 1)) [ 1 2 3 ..., 8 9 10] edgeitems: ? 123456 np.set_printoptions(threshold=5)print(np.arange(1, 11, 1)) [ 1 2 3 ..., 8 9 10] np.set_printoptions(threshold=5, edgeitems=4)print(np.arange(1, 11, 1)) [ 1 2 3 4 ..., 7 8 9 10] formatter ? 123 np.set_printoptions(formatter={'all': lambda x: 'int: ' + str(-x)})print(np.arange(1, 5, 1)) [int: -1 int: -2 int: -3 int: -4] 这个formatter是一个可调用的字典,'all'是其中一个key,表示里面的x可以包含所有type,还有其他key,具体可以在源码里面查看最后如果只想在代码中的某一部分使用自定义的printoptions,那么可以通过再次调用np.set_printoptions()这个方法来进行reset sublime也是一款常用的文本编辑器,当我们在对python文件进行编辑的时候,我们可以在首选项里进行配置来快速运行python文件; 方法/步骤我们用sublime打开一个python文件,我们要怎么运行它呢,如图所示;如何在sublime上运行python我们点击"首选项/浏览包",点开之后出来一个目录图形窗口,我们找到python文件夹,如果没有我们新建一个,如图所示;如何在sublime上运行python如何在sublime上运行python在python文件夹里,我们再建一个文件命名为 Python.sublime-commands,如图所示;如何在sublime上运行python然后我们写入如下内容,path那一行要换成自己的python安装路径;{"cmd":["python.exe", "-u", "$file"],"path":"D:python3.6","file_regex": "^[ ]File "(...?)", line ([0-9]*)","selector": "source.python"}如何在sublime上运行python修改好之后我们点击保存,我们点击"Tools/Bulid System/Python",如图所示;如何在sublime上运行python然后我们回到之前的python文件,我们点击"Tools/Bulid"(快捷键是Ctrl+B,后面就按快捷键了),可以看到运行的结果,如图所示;如何在sublime上运行python如何在sublime上运行python我们再打开一个有错误的python文件,运行看一下效果,如图所示;如何在sublime上运行python

xuning715 2019-12-02 01:10:43 0 浏览量 回答数 0

回答

Python 正则表达式正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。Python 自1.5版本起增加了re 模块,它提供 Perl 风格的正则表达式模式。re 模块使 Python 语言拥有全部的正则表达式功能。compile 函数根据一个模式字符串和可选的标志参数生成一个正则表达式对象。该对象拥有一系列方法用于正则表达式匹配和替换。re 模块也提供了与这些方法功能完全一致的函数,这些函数使用一个模式字符串做为它们的第一个参数。本章节主要介绍Python中常用的正则表达式处理函数。re.match函数re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。函数语法:re.match(pattern, string, flags=0)函数参数说明:参数 描述pattern 匹配的正则表达式string 要匹配的字符串。flags 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。参见:正则表达式修饰符 - 可选标志匹配成功re.match方法返回一个匹配的对象,否则返回None。我们可以使用group(num) 或 groups() 匹配对象函数来获取匹配表达式。匹配对象方法 描述group(num=0) 匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。groups() 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。实例 !/usr/bin/python -- coding: UTF-8 -- import reprint(re.match('www', 'www.runoob.com').span()) # 在起始位置匹配print(re.match('com', 'www.runoob.com')) # 不在起始位置匹配以上实例运行输出结果为:(0, 3)None实例 !/usr/bin/python import re line = "Cats are smarter than dogs" matchObj = re.match( r'(.) are (.?) .*', line, re.M|re.I) if matchObj: print "matchObj.group() : ", matchObj.group() print "matchObj.group(1) : ", matchObj.group(1) print "matchObj.group(2) : ", matchObj.group(2)else: print "No match!!"以上实例执行结果如下:matchObj.group() : Cats are smarter than dogsmatchObj.group(1) : CatsmatchObj.group(2) : smarterre.search方法re.search 扫描整个字符串并返回第一个成功的匹配。函数语法:re.search(pattern, string, flags=0)函数参数说明:参数 描述pattern 匹配的正则表达式string 要匹配的字符串。flags 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。匹配成功re.search方法返回一个匹配的对象,否则返回None。我们可以使用group(num) 或 groups() 匹配对象函数来获取匹配表达式。匹配对象方法 描述group(num=0) 匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。groups() 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。实例 !/usr/bin/python -- coding: UTF-8 -- import reprint(re.search('www', 'www.runoob.com').span()) # 在起始位置匹配print(re.search('com', 'www.runoob.com').span()) # 不在起始位置匹配以上实例运行输出结果为:(0, 3)(11, 14)实例 !/usr/bin/python import re line = "Cats are smarter than dogs"; searchObj = re.search( r'(.) are (.?) .*', line, re.M|re.I) if searchObj: print "searchObj.group() : ", searchObj.group() print "searchObj.group(1) : ", searchObj.group(1) print "searchObj.group(2) : ", searchObj.group(2)else: print "Nothing found!!"以上实例执行结果如下:searchObj.group() : Cats are smarter than dogssearchObj.group(1) : CatssearchObj.group(2) : smarterre.match与re.search的区别re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。实例 !/usr/bin/python import re line = "Cats are smarter than dogs"; matchObj = re.match( r'dogs', line, re.M|re.I)if matchObj: print "match --> matchObj.group() : ", matchObj.group()else: print "No match!!" matchObj = re.search( r'dogs', line, re.M|re.I)if matchObj: print "search --> matchObj.group() : ", matchObj.group()else: print "No match!!"以上实例运行结果如下:No match!!search --> matchObj.group() : dogs检索和替换Python 的 re 模块提供了re.sub用于替换字符串中的匹配项。语法:re.sub(pattern, repl, string, count=0, flags=0)参数:pattern : 正则中的模式字符串。repl : 替换的字符串,也可为一个函数。string : 要被查找替换的原始字符串。count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。实例 !/usr/bin/python -- coding: UTF-8 -- import re phone = "2004-959-559 # 这是一个国外电话号码" 删除字符串中的 Python注释 num = re.sub(r'#.*$', "", phone)print "电话号码是: ", num 删除非数字(-)的字符串 num = re.sub(r'D', "", phone)print "电话号码是 : ", num以上实例执行结果如下:电话号码是: 2004-959-559 电话号码是 : 2004959559repl 参数是一个函数以下实例中将字符串中的匹配的数字乘以 2:实例 !/usr/bin/python -- coding: UTF-8 -- import re 将匹配的数字乘以 2 def double(matched): value = int(matched.group('value')) return str(value * 2) s = 'A23G4HFD567'print(re.sub('(?Pd+)', double, s))执行输出结果为:A46G8HFD1134re.compile 函数compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用。语法格式为:re.compile(pattern[, flags])参数:pattern : 一个字符串形式的正则表达式flags : 可选,表示匹配模式,比如忽略大小写,多行模式等,具体参数为:re.I 忽略大小写re.L 表示特殊字符集 w, W, b, B, s, S 依赖于当前环境re.M 多行模式re.S 即为 . 并且包括换行符在内的任意字符(. 不包括换行符)re.U 表示特殊字符集 w, W, b, B, d, D, s, S 依赖于 Unicode 字符属性数据库re.X 为了增加可读性,忽略空格和 # 后面的注释实例实例 import repattern = re.compile(r'd+') # 用于匹配至少一个数字m = pattern.match('one12twothree34four') # 查找头部,没有匹配print m None m = pattern.match('one12twothree34four', 2, 10) # 从'e'的位置开始匹配,没有匹配print m None m = pattern.match('one12twothree34four', 3, 10) # 从'1'的位置开始匹配,正好匹配print m # 返回一个 Match 对象 <_sre.SRE_Match object at 0x10a42aac0> m.group(0) # 可省略 0 '12' m.start(0) # 可省略 0 3 m.end(0) # 可省略 0 5 m.span(0) # 可省略 0 (3, 5)在上面,当匹配成功时返回一个 Match 对象,其中:group([group1, …]) 方法用于获得一个或多个分组匹配的字符串,当要获得整个匹配的子串时,可直接使用 group() 或 group(0);start([group]) 方法用于获取分组匹配的子串在整个字符串中的起始位置(子串第一个字符的索引),参数默认值为 0;end([group]) 方法用于获取分组匹配的子串在整个字符串中的结束位置(子串最后一个字符的索引+1),参数默认值为 0;span([group]) 方法返回 (start(group), end(group))。再看看一个例子:实例 import repattern = re.compile(r'([a-z]+) ([a-z]+)', re.I) # re.I 表示忽略大小写m = pattern.match('Hello World Wide Web')print m # 匹配成功,返回一个 Match 对象 <_sre.SRE_Match object at 0x10bea83e8> m.group(0) # 返回匹配成功的整个子串 'Hello World' m.span(0) # 返回匹配成功的整个子串的索引 (0, 11) m.group(1) # 返回第一个分组匹配成功的子串 'Hello' m.span(1) # 返回第一个分组匹配成功的子串的索引 (0, 5) m.group(2) # 返回第二个分组匹配成功的子串 'World' m.span(2) # 返回第二个分组匹配成功的子串 (6, 11) m.groups() # 等价于 (m.group(1), m.group(2), ...) ('Hello', 'World') m.group(3) # 不存在第三个分组 Traceback (most recent call last): File "", line 1, in IndexError: no such groupfindall在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。注意: match 和 search 是匹配一次 findall 匹配所有。语法格式为:findall(string[, pos[, endpos]])参数:string : 待匹配的字符串。pos : 可选参数,指定字符串的起始位置,默认为 0。endpos : 可选参数,指定字符串的结束位置,默认为字符串的长度。查找字符串中的所有数字:实例 -- coding:UTF8 -- import re pattern = re.compile(r'd+') # 查找数字result1 = pattern.findall('runoob 123 google 456')result2 = pattern.findall('run88oob123google456', 0, 10) print(result1)print(result2)输出结果:['123', '456']['88', '12']re.finditer和 findall 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。re.finditer(pattern, string, flags=0)参数:参数 描述pattern 匹配的正则表达式string 要匹配的字符串。flags 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。参见:正则表达式修饰符 - 可选标志实例 -- coding: UTF-8 -- import re it = re.finditer(r"d+","12a32bc43jf3") for match in it: print (match.group() ) 输出结果:12 32 43 3re.splitsplit 方法按照能够匹配的子串将字符串分割后返回列表,它的使用形式如下:re.split(pattern, string[, maxsplit=0, flags=0])参数:参数 描述pattern 匹配的正则表达式string 要匹配的字符串。maxsplit 分隔次数,maxsplit=1 分隔一次,默认为 0,不限制次数。flags 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。参见:正则表达式修饰符 - 可选标志实例 import rere.split('W+', 'runoob, runoob, runoob.')['runoob', 'runoob', 'runoob', '']re.split('(W+)', ' runoob, runoob, runoob.') ['', ' ', 'runoob', ', ', 'runoob', ', ', 'runoob', '.', ''] re.split('W+', ' runoob, runoob, runoob.', 1) ['', 'runoob, runoob, runoob.'] re.split('a*', 'hello world') # 对于一个找不到匹配的字符串而言,split 不会对其作出分割 ['hello world']正则表达式对象re.RegexObjectre.compile() 返回 RegexObject 对象。re.MatchObjectgroup() 返回被 RE 匹配的字符串。start() 返回匹配开始的位置end() 返回匹配结束的位置span() 返回一个元组包含匹配 (开始,结束) 的位置正则表达式修饰符 - 可选标志正则表达式可以包含一些可选标志修饰符来控制匹配的模式。修饰符被指定为一个可选的标志。多个标志可以通过按位 OR(|) 它们来指定。如 re.I | re.M 被设置成 I 和 M 标志:修饰符 描述re.I 使匹配对大小写不敏感re.L 做本地化识别(locale-aware)匹配re.M 多行匹配,影响 ^ 和 $re.S 使 . 匹配包括换行在内的所有字符re.U 根据Unicode字符集解析字符。这个标志影响 w, W, b, B.re.X 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。正则表达式模式模式字符串使用特殊的语法来表示一个正则表达式:字母和数字表示他们自身。一个正则表达式模式中的字母和数字匹配同样的字符串。多数字母和数字前加一个反斜杠时会拥有不同的含义。标点符号只有被转义时才匹配自身,否则它们表示特殊的含义。反斜杠本身需要使用反斜杠转义。由于正则表达式通常都包含反斜杠,所以你最好使用原始字符串来表示它们。模式元素(如 r't',等价于 '\t')匹配相应的特殊字符。下表列出了正则表达式模式语法中的特殊元素。如果你使用模式的同时提供了可选的标志参数,某些模式元素的含义会改变。模式 描述^ 匹配字符串的开头$ 匹配字符串的末尾。. 匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。[...] 用来表示一组字符,单独列出:[amk] 匹配 'a','m'或'k'1 不在[]中的字符:2 匹配除了a,b,c之外的字符。re* 匹配0个或多个的表达式。re+ 匹配1个或多个的表达式。re? 匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式re{ n} 精确匹配 n 个前面表达式。例如, o{2} 不能匹配 "Bob" 中的 "o",但是能匹配 "food" 中的两个 o。re{ n,} 匹配 n 个前面表达式。例如, o{2,} 不能匹配"Bob"中的"o",但能匹配 "foooood"中的所有 o。"o{1,}" 等价于 "o+"。"o{0,}" 则等价于 "o*"。re{ n, m} 匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式a| b 匹配a或b(re) 匹配括号内的表达式,也表示一个组(?imx) 正则表达式包含三种可选标志:i, m, 或 x 。只影响括号中的区域。(?-imx) 正则表达式关闭 i, m, 或 x 可选标志。只影响括号中的区域。(?: re) 类似 (...), 但是不表示一个组(?imx: re) 在括号中使用i, m, 或 x 可选标志(?-imx: re) 在括号中不使用i, m, 或 x 可选标志(?#...) 注释.(?= re) 前向肯定界定符。如果所含正则表达式,以 ... 表示,在当前位置成功匹配时成功,否则失败。但一旦所含表达式已经尝试,匹配引擎根本没有提高;模式的剩余部分还要尝试界定符的右边。(?! re) 前向否定界定符。与肯定界定符相反;当所含表达式不能在字符串当前位置匹配时成功(?> re) 匹配的独立模式,省去回溯。w 匹配字母数字及下划线W 匹配非字母数字及下划线s 匹配任意空白字符,等价于 [tnrf].S 匹配任意非空字符d 匹配任意数字,等价于 [0-9].D 匹配任意非数字A 匹配字符串开始Z 匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串。z 匹配字符串结束G 匹配最后匹配完成的位置。b 匹配一个单词边界,也就是指单词和空格间的位置。例如, 'erb' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。B 匹配非单词边界。'erB' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。n, t, 等. 匹配一个换行符。匹配一个制表符。等1...9 匹配第n个分组的内容。10 匹配第n个分组的内容,如果它经匹配。否则指的是八进制字符码的表达式。正则表达式实例字符匹配实例 描述python 匹配 "python".字符类实例 描述[Pp]ython 匹配 "Python" 或 "python"rub[ye] 匹配 "ruby" 或 "rube"[aeiou] 匹配中括号内的任意一个字母[0-9] 匹配任何数字。类似于 [0123456789][a-z] 匹配任何小写字母[A-Z] 匹配任何大写字母[a-zA-Z0-9] 匹配任何字母及数字3 除了aeiou字母以外的所有字符4 匹配除了数字外的字符特殊字符类实例 描述. 匹配除 "n" 之外的任何单个字符。要匹配包括 'n' 在内的任何字符,请使用象 '[.n]' 的模式。d 匹配一个数字字符。等价于 [0-9]。D 匹配一个非数字字符。等价于 4。s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ fnrtv]。S 匹配任何非空白字符。等价于 5。w 匹配包括下划线的任何单词字符。等价于'[A-Za-z0-9_]'。W 匹配任何非单词字符。等价于 '6'。 Python 面向对象 Python CGI编程 1 篇笔记 jim 264*7522@qq.com正则表达式实例: !/usr/bin/python import reline = "Cats are smarter than dogs"matchObj = re.match( r'(.) are (.?) .*', line, re.M|re.I)if matchObj: print "matchObj.group() : ", matchObj.group() print "matchObj.group(1) : ", matchObj.group(1) print "matchObj.group(2) : ", matchObj.group(2) else: print "No match!!" 正则表达式:r'(.) are (.?) .*'解析:首先,这是一个字符串,前面的一个 r 表示字符串为非转义的原始字符串,让编译器忽略反斜杠,也就是忽略转义字符。但是这个字符串里没有反斜杠,所以这个 r 可有可无。 (.) 第一个匹配分组,. 代表匹配除换行符之外的所有字符。 (.?) 第二个匹配分组,.? 后面多个问号,代表非贪婪模式,也就是说只匹配符合条件的最少字符 后面的一个 .* 没有括号包围,所以不是分组,匹配效果和第一个一样,但是不计入匹配结果中。matchObj.group() 等同于 matchObj.group(0),表示匹配到的完整文本字符matchObj.group(1) 得到第一组匹配结果,也就是(.*)匹配到的matchObj.group(2) 得到第二组匹配结果,也就是(.*?)匹配到的因为只有匹配结果中只有两组,所以如果填 3 时会报错。 ... ↩ abc ↩ aeiou ↩ 0-9 ↩ fnrtv ↩ A-Za-z0-9_ ↩

xuning715 2019-12-02 01:10:40 0 浏览量 回答数 0
阿里云大学 云服务器ECS com域名 网站域名whois查询 开发者平台 小程序定制 小程序开发 国内短信套餐包 开发者技术与产品 云数据库 图像识别 开发者问答 阿里云建站 阿里云备案 云市场 万网 阿里云帮助文档 免费套餐 开发者工具 企业信息查询 小程序开发制作 视频内容分析 企业网站制作 视频集锦 代理记账服务 2020阿里巴巴研发效能峰会 企业建站模板 云效成长地图 高端建站