使用 AWS SNS 发送通知到 HTTP 终端
该文章根据 CC-BY-4.0 协议发表,转载请遵循该协议。
本文地址:https://fenying.net/post/2016/08/27/use-aws-sns-with-a-http-endpoint/
文章目录
AWS 的 SNS 是一个消息推送服务,通过 SNS,可以将 AWS 的其他服务(如 S3)的事件消息转发给 其它终端(E-Mail,HTTP服务器等)。
其它终端(E-Mail,HTTP服务器等)。
一般情况下 SNS 的消息是一次性的,发完就消失了,当然也可以配置延迟发送的消息,这里只讲第一种。
下面直接开始说使用方式。
1. 创建 SNS 主题
主题是指一个消息集合,一个主题可储存多条消息,其他 AWS 服务可以将某些消息发到这个 SNS 主题下。
订阅是指:谁订阅了这个主题,主题就将其中的消息分发给这些订阅者,例如 HTTP 终端。
在使用之前必须先至少创建一个 SNS 主题,主题名称为 test,显示名随意。
2. 创建一个订阅(HTTP为例)
创建号了 SNS 主题后,下面有一个很大的按钮,叫你创建订阅,但是,先不要理他!
因为你一旦创建了一个订阅,AWS 马上就会发一个确认请求到那个地址——明显你应该还没准备好。
下面我们先说说怎么确认。 »> 官方教程 «<
不过官方教程有点长,我这里直接说最简单的方法。
AWS SNS 做这个确认订阅操作,就像我们注册网站账户的时候要验证邮箱或者手机一样,确认这个 HTTP 终端是你在用,否则你随便添加一个 HTTP 地址,天天叫 AWS 发请求,岂不是麻烦大了。
这就是确认订阅的目的。
当然了,确认订阅也和我们注册账户很像,它发送一个 HTTP POST 请求到你的地址,比如我这是 http://fenying.net/aws/sns/test/,当然了,这个地址是骗你们的。
它发送的 HTTP Body 是一个 JSON 结构,其中字段 SubscribeURL
里面是确认地址,用 HTTP GET
调用这个地址就可以完成订阅确认,这里用 PHP 代码处理:
1<?php
2/**
3 * /aws/sns/test/index.php
4 */
5$rawData = file_get_contents('php://input');
6$_POST = json_decode($rawData);
7
8$ch = curl_init($_POST->SubscribeURL) ;
9
10curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
11curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
12curl_exec($ch) ;
13curl_close($ch);
现在我们来创建一个 HTTP 类型的订阅,地址写你的处理地址,我这里是 http://fenying.net/aws/sns/test/。
创建完成,AWS 会发送一个确认请求到上面的地址。
3. 绑定 S3 Bucket 和 SNS
首先给我们的 SNS 主题 test 添加策略,修改为所有人都可以发消息。
然后进入 S3 控制台,选择一个 Bucket 查看属性,在 Events 栏里面添加一个事件,我选择的是
PUT,然后选择我们的 test SNS 主题,随便写个前缀(这里用 upload/
)和名称,然后保存。
有没有绑定成功现在还无法确认,因为我们没有修改代码。下面写个简单的 DEMO:
1<?php
2/**
3 * /aws/sns/test/index.php
4 */
5file_put_contents(
6 's3.sns.log',
7 $_SERVER['REQUEST_URI'] . PHP_EOL .
8 json_encode($_SERVER, 1) . PHP_EOL .
9 file_get_contents('php://input') . PHP_EOL . PHP_EOL,
10 FILE_APPEND
11);
设置完毕,下面开始测试吧,上传一个文件到刚才的储存桶下面,key 比如 upload/test.zip
。
然后去我们的服务器上查看下 s3.sns.log 文件,就可以得到具体的请求数据结构了。
4. 安全检测
我们的 HTTP 终端需要检测是否调用信息来自 AWS SNS,一个最简单的方法是根据 SNS Topic ARN 判断,
请求的 SNS Topic ARN 通过 $_SERVER['HTTP_X_AMZ_SNS_TOPIC_ARN']
可以获取到,即 HTTP
请求头里面的字段 x-amz-sns-topic-arn
。
SNS Topic 的 ARN 可以在 SNS 控制台看到,一个典型的 SNS Topic ARN 是一个
arn:aws:sns:us-east-1:123456789012:sample
。
当然,还有更安全的方法是,使用亚马逊提供的哈希校验算法,根据 POST 的 JSON 里面的字段实现, 这个比较复杂,就不说明了,请查看官方文档。
(完)