开发者社区> 张医博> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

OSS signature 计算

简介: 场景 通过多个语言版本 OSS SDK 测试,在使用 CDN 结合 OSS 用法时,客户端使用 CDN 域名计算 signature,发起 HEAD 请求,OSS 收到后返回 403 ; 分析: 出现这个问题不区分什么 SDK 都会出现,问题原因是由于客户端发起的 HEAD 请求在通过 CDN 回原到 OSS 时,CDN 回原是用的 GET 请求,而 OSS 收到时就用 GET 请求方式去计算签名,得到的结果肯定和客户端计算不一致,可以升级到阿里云 CDN 处理。
+关注继续查看

背景

出现 signature 一般出现客户端自签名调 API 的操作中, signature 的计算稍微复杂点,建议最好用 SDK 来替代计算的过程和多样性。如果业务强需求,先要读懂如果计算 signature。

签名分类

Header 头中携带签名。

https://help.aliyun.com/document_detail/31951.html?spm=a2c4g.11174283.6.1078.40437da2HGkyMH

URL 中携带签名。

https://help.aliyun.com/document_detail/31952.html?spm=a2c4g.11186623.6.1079.7b61734cNAir2U

签名区别

Header URL
不支持设置 expires 支持设置 expires
常用 method GET、POST、PUT 常用 method GET、PUT
date 时间是 GMT 格式 date 替换成 expires 变成时间戳
signature 不需要 URL encode signature 需要 URL encode

计算签名 demo

当客户通过 header 或者 URL 中自签名计算 signature 时,经常会遇到计算签名失败 “The request signature we calculated does not match the signature you provided” ,可以参考以下 demo 演示了如何调用 API 自签名时上传 Object 到 OSS,注意签名和 header 加入的内容。

#! /us/bin/envy python
#Author: hanli
#Update: 2018-09-29

from optparse import OptionParser
import urllib, urllib2
import datetime
import base64
import hmac
import sha
import os
import sys
import time


class Main():
  
  # Initial input parse

  def __init__(self,options):

    self.ak = options.ak
    self.sk = options.sk
    self.ed = options.ed
    self.bk = options.bk
    self.fi = options.fi
    self.oj = options.objects
    self.left = '\033[1;31;40m'
    self.right = '\033[0m'
    self.types = "application/x-www-form-urlencoded"    
    self.url = 'http://{0}.{1}/{2}'.format(self.bk,self.ed,self.oj)

  # Check client input parse

  def CheckParse(self):

    if (self.ak and self.sk and self.ed and self.bk and self.oj and self.fi) != None:
      if str(self.ak and self.sk and self.ed and self.bk and self.oj and self.fi):
        self.PutObject()
    else:
      self.ConsoleLog("error","Input parameters cannot be empty")

  # GET local GMT time

  def GetGMT(self):
  
    SRM = datetime.datetime.utcnow()
    GMT = SRM.strftime('%a, %d %b %Y %H:%M:%S GMT')
    
    return GMT

  # GET Signature

  def GetSignature(self):

    mac = hmac.new("{0}".format(self.sk),"PUT\n\n{0}\n{1}\n/{2}/{3}".format(self.types,self.GetGMT(),self.bk,self.oj), sha)
    Signature = base64.b64encode(mac.digest())
   
    return Signature

  # PutObject

  def PutObject(self):
   
    try: 
      with open(self.fi) as fd:
        files = fd.read()
    except Exception as e:
      self.ConsoleLog("error",e)
  
    try:
      request = urllib2.Request(self.url, files)
      request.add_header('Host','{0}.{1}'.format(self.bk,self.ed))
      request.add_header('Date','{0}'.format(self.GetGMT()))
      request.add_header('Authorization','OSS {0}:{1}'.format(self.ak,self.GetSignature()))
      request.get_method = lambda:'PUT'
      response = urllib2.urlopen(request,timeout=10)
      fd.close()
      self.ConsoleLog(response.code,response.headers)
    except Exception,e:
      self.ConsoleLog("error",e)
 
  # output error log

  def ConsoleLog(self,level=None,mess=None):

    if level == "error":
      sys.exit('{0}[ERROR:]{1}{2}'.format(self.left,self.right,mess))
    else:
      sys.exit('\nHTTP/1.1 {0} OK\n{1}'.format(level,mess))

if __name__ == "__main__":

  parser = OptionParser()
  parser.add_option("-i",dest="ak",help="Must fill in Accesskey")
  parser.add_option("-k",dest="sk",help="Must fill in AccessKeySecrety")
  parser.add_option("-e",dest="ed",help="Must fill in endpoint")
  parser.add_option("-b",dest="bk",help="Must fill in bucket")
  parser.add_option("-o",dest="objects",help="File name uploaded to oss")
  parser.add_option("-f",dest="fi",help="Must fill localfile path")

  (options, args) = parser.parse_args()
  handler = Main(options)
  handler.CheckParse()

请求头:

PUT /yuntest HTTP/1.1
Accept-Encoding: identity
Content-Length: 147
Connection: close
User-Agent: Python-urllib/2.7
Date: Sat, 22 Sep 2018 04:36:52 GMT
Host: yourBucket.oss-cn-shanghai.aliyuncs.com
Content-Type: application/x-www-form-urlencoded
Authorization: OSS B0g3mdt:lNCA4L0P43Ax

响应头:

HTTP/1.1 200 OK
Server: AliyunOSS
Date: Sat, 22 Sep 2018 04:36:52 GMT
Content-Length: 0
Connection: close
x-oss-request-id: 5BA5C6E4059A3C2F
ETag: "D0CAA153941AAA1CBDA38AF"
x-oss-hash-crc64ecma: 8478734191999037841
Content-MD5: 0MqhU5QbIp3Ujqqhy9o4rw==
x-oss-server-time: 15

注意

  • Signature 中所有加入计算的参数都要放在 header 中,保持 header 和 Signature 一致。
  • PUT 上传时,Signature 计算的 Content-Type 必须是 application/x-www-form-urlencoded 。
  • 通过header 方式进行签名认证时无法设置过期时间。目前只有 SDK 、URL 签名支持设置过期时间。

使用问题

案例:通过微信小程序请求 OSS 返回签名失败,通过浏览器正常

分析:

  • 只要通过浏览器访问,鉴权通过就证明 OSS 的签名校验是正常的没有问题,可以先排除掉 OSS 端。
  • 客户端一定要在微信小程序上部署 HTTP 抓包,对后续分析很重要,抓包中可以看到所有的请求头和请求参数。
  • 通过浏览器访问时的 HTTP 抓包。

5

  • 通过 403 和 200 的抓包反复对比发现,通过小程序发出的 HTTP 请求和浏览器发起的 HTTP 请求的 URL 、signature、expires 都一样,唯一的区别就是微信小程序携带了 Content-type ,而通过 Chrom 的请求是没有携带 Content-type,怀疑矛头指向了这里。
  • 经过代码确认,发现 signature 计算时是没有包含 Content-tpye 头的,而小程序发起的请求携带的 Content-tpye ,OSS 收到后会按照携带了 Content-tpye 去计算 signature ,所以每次计算都不一样。

遇到类似问题,抓包是最能快速看到问题的。同时也必须要了解下 OSS 请求 header 中携带了 Content-tpye ,那么 signature 计算就要加上 Content-tpye ,保持一致。

案例:通过多个语言版本 OSS SDK 测试,在使用 CDN 结合 OSS 用法时,客户端使用 CDN 域名计算 signature,发起 HEAD 请求,OSS 收到后返回 403 ;

1

分析:

出现这个问题不区分什么 SDK 都会出现,问题原因是由于客户端发起的 HEAD 请求在通过 CDN 回原到 OSS 时,CDN 回原是用的 GET 请求,而 OSS 收到时就用 GET 请求方式去计算签名,得到的结果肯定和客户端计算不一致,可以升级到阿里云 CDN 处理。以上分析只适合上述场景。

问题可以通过 tcpdump 抓包或者 Wireshark 对比一下即可知道。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
oss资源访问连接问题
ssl证书 域名绑定 自有域名
0 0
CEN+私网NAT实现跨地域访问OSS需求-CEN基础版
CEN+私网NAT实现跨地域访问OSS需求-CEN基础版
0 0
通过OSS外表访问OSS数据
原文地址:通过OSS外表访问OSS数据 - 云原生关系型数据库 PolarDB MySQL引擎 - 阿里云PolarDB可以通过OSS外表直接查询存储在OSS上的CSV格式数据,有效地降低存储的成本。本文档主要介绍了通过OSS外表访问OSS数据的操作步骤。背景信息通过OSS外表,您可以把CSV格式的冷数据存储在OSS引擎上,并对冷数据进行查询和分析。具体原理如下:CSV格式的数据支持的数据类型包括
0 0
访问 OSS 这类对象存储最快的方式- JindoFS SDK |学习笔记
快速学习 访问 OSS 这类对象存储最快的方式- JindoFS SDK
0 0
Hadoop/Spark 访问 OSS 加速 | 学习笔记
快速学习Hadoop/Spark 访问 OSS 加速。
0 0
Spark 访问 OSS 透明缓存加速 | 学习笔记
快速学习Spark 访问 OSS 透明缓存加速。
0 0
Presto 访问 OSS 透明缓存加速 | 学习笔记
快速学习 Presto 访问 OSS 透明缓存加速。
0 0
访问oss出现报错:You have no right to access this object because of bucket acl
访问oss出现报错:You have no right to access this object because of bucket acl 也配置bucket权限和RAM用户权限了但是还是报错,然后看了下代码,发现到httpClient.execute(req)就直接403了 能问下大佬们这是什么问题吗,百度也没找到
0 0
基于访问日志实现OSS监控
对象存储OSS是阿里云提供的云存储服务,能够以低成本为用户提供高可靠性的海量数据存储服务。作为基础服务,用户需要时刻关注OSS的使用状况,检测异常状态,从而及时作出响应。
0 0
+关注
张医博
喜欢钻研新的语言,动手实践自己想要学会的知识。
文章
问答
来源圈子
更多
作为全球云计算的领先者,阿里云为全球230万企业提供着云计算服务,服务范围覆盖200多个国家和地区。我们致力于为企业、政府等组织机构提供安全可靠的云计算服务,给用户带来极速愉悦的服务体验。
+ 订阅
相关文档: 迁云实施服务
文章排行榜
最热
最新
相关电子书
更多
百问百答-OSS (上)
立即下载
百问百答-OSS (下)
立即下载
阿里云 JindoFS+OSS 数据上云实战
立即下载