使用amazon的S3服务

yujs0000 2013-06-15

需求背景:

      今天帮同学解决一个问题,对方给了一个英文文档,intel那边只给了一些文章id(文章ID是放在很多个文件的json数组里的.),要把文章内容拿到在平板上进行展示.

      我看了下文档上提供了两种方案,第一种是通过AWS的方式.第二种直接通过URL把文章内容呈现出来.

比较而言,第二种通过http请求,只需要生成token信息,在带上文章ID,发出一个请求后,拿到真正的文章的URL就基本搞定了.再次请求,直接把返回的页面内容展示出来即可.

      但是同学的需求是,希望拿到一些信息按照自己的方式来展示.而第一种方法,是通过文章id获取json信息(里面包含了文章的一些元数据,比如标题,内容,图片等),这样的信息就可以根据自己的需要灵活展现了.

难点是这个要访问S3进行获取,于是去网上研究了下S3.

S3是啥?

英文含义为:Simple storage serviece (简称S3),顾名思义,提供存储服务,这是一个公开的服务,使 Web 开发人员能够存储数字资产(如图片、视频、音乐和文档等),以便在应用程序中使用。

Amazon 的 S3 服务没有重复开发,它公开了 RESTful API,使您能够使用任何支持 HTTP 通信的语言访问 S3 。关于REST,这也是比较火的一种Web服务架构。简单来说,资源是由URI指定,对资源的操作包括GET、PUT、POST、DELETE和HEAD,返回结果常常是XML或者其他形式。

S3里的几个概念:

Amazon S3的操作包括三部分:Service,Buckets和Objects。Service只包括GET操作,就是返回所有的Buckets的列表。Object顾名思义,是指存储在云端的文件,值得注意的是,S3中并没有明确的文件夹的概念,而是通过指定object的路径来实现,比如说,object可以为“photos/1.jpg”。而Bucket拥有全局名,名称由用户定义,用来存放Object,由于是全局名,所以要确保名字是别人没用过的。

通过REST的方式访问资源,根据官方文档:

http://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html#ConstructingTheAuthenticationHeader

在S3上注册后,会给你Access Key Id和Secret Access Key.前者是标识你的身份,后者是秘钥用来生成签名,确保内容安全.无论是创建bucket,还是对object进行操作,都需要经过系统的认证才行.

在发出请求时,请求方会对请求内容通过HMAC-SHA1算法生成签名.

在服务端收到请求后,会再次针对请求内容生成签名,与请求发过来的签名进行对比,如果一致,则为合法,否则认证不通过.

发出的请求格式大致如下:

GET /photos/puppy.jpg HTTP/1.1
Host: johnsmith.s3.amazonaws.com
Date: Mon, 26 Mar 2007 19:37:58 +0000

Authorization: AWS AKIAIOSFODNN7EXAMPLE:frJIUN8DYpKDtOLCwo//yllqDzg=

 重点是Authorization这个串的生成.由如下部分组成:

Authorization: AWS AWSAccessKeyId:Signature

 如下是构建认证请求头的伪代码:

Authorization = "AWS" + " " + AWSAccessKeyId + ":" + Signature;

Signature = Base64( HMAC-SHA1( YourSecretAccessKeyID, UTF-8-Encoding-Of( StringToSign ) ) );

StringToSign = HTTP-Verb + "\n" +
	Content-MD5 + "\n" +
	Content-Type + "\n" +
	Date + "\n" +
	CanonicalizedAmzHeaders +
	CanonicalizedResource;

CanonicalizedResource = [ "/" + Bucket ] +
	<HTTP-Request-URI, from the protocol name up to the query string> +
	[ sub-resource, if present. For example "?acl", "?location", "?logging", or "?torrent"];

CanonicalizedAmzHeaders = <described below>

 代码例子:

 把同学的例子按照python的方式进行编写的话,如下:

#-*- coding: utf-8 -*-
import urllib2
import hashlib
import datetime
import base64
import exceptions
import hmac

GMT_FORMAT = '%a, %d %b %Y %H:%M:%S GMT'
MyAccessKey = 'xxxxxxxxxxx'
MySecretKey = 'xxxxxxxxxxxxxxxxxxxxxxxxxxx'

myDate = datetime.datetime.utcnow().strftime(GMT_FORMAT)

def authStr():
    mystr = "GET\n\n\n" + myDate + "\n/tmc-json/70226.json"
    myhmac = hmac.new(MySecretKey, digestmod=hashlib.sha1)
    myhmac.update(mystr)
    signStr=base64.encodestring( myhmac.digest())
    result = "AWS %s:%s" % (MyAccessKey, signStr)
    return result.strip()


def start():
    req = urllib2.Request('http://s3.amazonaws.com/tmc-json/70226.json')
    req.add_header('Date', myDate)
    req.add_header('AWSAccessKeyId', MyAccessKey)
    req.add_header('Authorization', authStr())
    print req.headers
    response = urllib2.urlopen(req)
    print response.read()

if __name__ == "__main__":
    start()

因为我们是get信息,所以请求头里的Content-MD5,Content-Type等信息默认可以为空.但是换行符什么的还是要有的.  这里的tmc-json就是一个bucket,70226是文章的id.最终认证通过可以获取到文章的json信息.

多插一句,如果通过js来做这个事情,就是要找支持这个加密算法的类库了.

https://code.google.com/p/crypto-js/#HMAC

参考如下代码:

<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/hmac-sha256.js"></script>
<script>
    var hmac = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, "Secret Passphrase");

    hmac.update("Message Part 1");
    hmac.update("Message Part 2");
    hmac.update("Message Part 3");

    var hash = hmac.finalize();
</script>

 参考资源链接:

http://www.lixin.me/blog/2012/01/28/29213 

http://aws.amazon.com/cn/console/ 

http://www.91r.net/ask/15599337.html

http://www.ibm.com/developerworks/cn/java/j-s3/ IBM上的文章提到了一个java类库: JetS3t可以简化实现类似的效果.

相关推荐