Azure Service Bus 中的身份验证方式 Shared Access Signature

警告

您当前查看的页面是未经授权的转载!
如果当前版本排版错误,请前往查看最新版本:http://www.cnblogs.com/qin-nz/p/azure-service-bus-shared-access-signature-token.html

提示

更新时间:2016年01月01日。

今天踩了一个坑……

在 Azure 的 Service Bus (服务总线) 中,每个请求是需要保护一个验证信息的。
这个验证信息可以是SAS,也可以是ACS(已经不建议使用)。

注解

如果是可以安全保存Key的服务器想要访问 Service Bus,并且不是使用.NET Core,是不需要知道有SAS Token 这种东西存在的。

小技巧

Azure Storage 对于非public的文件方法也是使用这个的思想,但用于签名的具体参数不同。

Shared Access Signature 机制

Shared Access Signature ,从名字上不难看出,这是一个通过签名来共享访问权限的机制。
在 Service Bus 中,我们有一个名为 RootManageSharedAccessKey 的Key,
这个 Key 拥有这个 Service Bus 的完整访问权限。
我们可以为每个队列/主题/事件中心 创建独立的Key,甚至可以为他们分配不同的权限。

注解

在管理门户中看到的 Key 一般有两个, PrimaryKeySecondaryKey ,任意一个都可用。
两个的目的是方便定期更换密钥,建议使用 PrimaryKey

由于 Service Bus 的发送方可能是终端设备,比如IoT设备等,就这样把Key下发下去很不安全,因此可以 Shared Access Signature 机制。

当我们需要访问某个资源,如 https://qinnz.servicebus.windows.net/myeventhub/message 时,
我们用刚刚的key对这个资源和可访问的有效期进行签名,并把签名+资源+有效期三项内容发给服务器,服务器即可进行签名验证。

Shared Access Signature 生成过程

这里,我们就用 RootManageSharedAccessKey 密钥进行签名。

  • 对资源Uri进行encode,资源Uri可以是请求的资源或者它的父资源。
  • 得到过期时间的Unix时间戳(Azure Storage 使用的是人可识别的日期格式)
  • 将Key使用 UTF-8 编码转换为字节数组,作为签名密钥
  • 对资源uri和时间戳进行签名(使用 HMAC-SHA256 算法)
  • 生成签名字符串
 1
2
3
4
5
6
7
8
9
10
11
12
13
14
    public class SasToken
{
public static string Generator(string uri, DateTimeOffset expiryTime, string keyName, string keyValue)
{
string uriEncoded = Uri.EscapeDataString(uri.ToString());
long expiry = expiryTime.ToUnixTimeSeconds(); //Only available on .Net 4.6
byte[] key = Encoding.UTF8.GetBytes(keyValue);
var hmac = new HMACSHA256(key);
string stringToSign = uriEncoded + "\n" + expiry.ToString();
string signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));
Debug.WriteLine(stringToSign);
return $"SharedAccessSignature sr={uriEncoded}&sig={Uri.EscapeDataString(signature)}&se={expiry}&skn={keyName}";
}
}

嗯,上面就是我自己实现的……坑就在于第7行……

在微软官方文档中,他们也以为是 base64 编码的,我刚刚在Github上提交了这个 issue

事实上,微软官方是有C#类库来做这件事的(下面第15行);
我自己实现仅为了能在别的平台上能用。
下面说说官方给出的实现代码和我的代码做比较,注意替换自己的key和keyName:

 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
using System;
using Microsoft.ServiceBus; namespace SharedAccessSignatureTokenGenerator
{
class Program
{
private static string resource = "<your-resource>";
private static string key = "<your-key-for-RootManageSharedAccessKey>";
private static string keyName = "RootManageSharedAccessKey"; static void Main(string[] args)
{
// Get Token using Microsoft.ServiceBus.SharedAccessSignatureTokenProvider.GetSharedAccessSignature
var token = SharedAccessSignatureTokenProvider.GetSharedAccessSignature(keyName, key, resource, new TimeSpan(24, 0, 0)); //Get Token using my SasToken.Generator
long se = long.Parse(token.Substring(token.IndexOf("se=") + 3, 10));
var mytoken = SasToken.Generator(resource, new DateTimeOffset(2050, 1, 1, 0, 0, 0, new TimeSpan()), keyName, key); Console.WriteLine(mytoken);
Console.WriteLine(token);
}
}
}

注解

由于我使用的 Uri.EscapeDataString 返回的是大写字母,造成签名值不一样;不过因为sr同样不一样,并没有什么影响。

可以使用 uriEncoded=uriEncoded.ToLower(); 使得两种方法签名一致。

访问测试

现在,就可以向 Service Bus 发送消息了。

注解

Event Hub 的API可以参考 这里

例如我们可以向 sb://qinnz.servicebus.windows.net/mail/messages 发送消息,
可以指定 srsb://qinnz.servicebus.windows.net/mail/messages
sb://qinnz.servicebus.windows.net (如果key的权限足够,那么此时的SAS具有整个servicebus的访问权限)
我们需要设定SAS的过期时间,已经你使用的密钥的名字,使Azure可以在服务器端验证签名。

最终,我们生成下面的字符串作为HTTP请求的Authorization请求头。

SharedAccessSignature sr=sb%3A%2F%2Fqinnz.servicebus.windows.net%2Fmail%2Fmessages
&sig=Augn3gnz4PEz%2Faaaaaaaaaaaaaaaaaaaacr%2B4vd2tWE%3D
&se=2000000000&skn=RootManageSharedAccessKey

下面我就用 Fiddler 模拟发送POST请求,内容如下(处于安全原因,我替换了签名值):

1
2
3
4
5
6
7
POST https://qinnz.servicebus.windows.net/mail/messages
Authorization: SharedAccessSignature sr=sb%3A%2F%2Fqinnz.servicebus.windows.net%2Fmail%2Fmessages&sig=Augn3gnz4PEz%2Faaaaaaaaaaaaaaaaaaaacr%2B4vd2tWE%3D&se=2000000000&skn=RootManageSharedAccessKey
Content-Type: application/atom+xml;type=entry;charset=utf-8
Host: qin-nz.servicebus.windows.net
Content-Length: 5 hello!

声明

Azure Service Bus 中的身份验证方式 Shared Access Signature 由 勤奋的小孩 创作,采用 知识共享 署名-相同方式共享 4.0 国际 许可协议进行许可。
本许可协议授权之外的使用权限可以从 http://space.cnblogs.com/msg/send/qin-nz 处获得。

Azure Service Bus 中的身份验证方式 Shared Access Signature的更多相关文章

  1. 【Azure 服务总线】Azure Service Bus中私信(DLQ - Dead Letter Queue)如何快速清理

    在博文ServiceBus 队列中死信(DLQ - Dead Letter Queue)问题一文中,介绍了服务总线产生私信的原因及可以通过代码的方式来清楚私信队列中的消息,避免长期占用空间(因为私信中 ...

  2. Azure Service Bus(二)在NET Core 控制台中如何操作 Service Bus Queue

    一,引言 上一篇讲到关于 Azure ServiceBus 的一些概念,讲到 Azure Service Bus(服务总线),其实也叫 "云消息服务",是微软在Azure 上提供的 ...

  3. Windows Azure Service Bus (3) 队列(Queue) 使用VS2013开发Service Bus Queue

    <Windows Azure Platform 系列文章目录> 在之前的Azure Service Bus中,我们已经介绍了Service Bus 队列(Queue)的基本概念. 在本章中 ...

  4. Windows Azure Service Bus Notification Hub推送通知

    前言 随着Windows Azure 在中国的正式落地,相信越来越多的人会体验到Windows Azure带来的强大和便利.在上一篇文章中, 我们介绍了如何利用Windows Azure中的Servi ...

  5. 【Azure 服务总线】详解Azure Service Bus SDK中接收消息时设置的maxConcurrentCalls,prefetchCount参数

    (Azure Service Bus服务总线的两大类消息处理方式: 队列Queue和主题Topic) 问题描述 使用Service Bus作为企业消息代理,当有大量的数据堆积再Queue或Topic中 ...

  6. 如何在ASP.NET Core中使用Azure Service Bus Queue

    原文:USING AZURE SERVICE BUS QUEUES WITH ASP.NET CORE SERVICES 作者:damienbod 译文:如何在ASP.NET Core中使用Azure ...

  7. asp.net中常用的几种身份验证方式

    转载:http://www.cnblogs.com/dinglang/archive/2012/06/03/2532664.html   前言 在B/S系统开发中,经常需要使用"身份验证&q ...

  8. 【服务总线 Azure Service Bus】ServiceBus 队列中死信(DLQ - Dead Letter Queue)问题

    Azure Service Bus 死信队列产生的原因 服务总线中有几个活动会导致从消息引擎本身将消息推送到 DLQ. 如 超过 MaxDeliveryCount 超过 TimeToLive 处理订阅 ...

  9. Windows Azure Service Bus (6) 中继(Relay On) 使用VS2013开发Service Bus Relay On

    <Windows Azure Platform 系列文章目录> 注意:本文介绍的是国内由世纪互联运维的Windows Azure服务. 项目文件请在这里下载. 我们在使用Azure平台的时 ...

随机推荐

  1. express 不是内部命令

    express4.0版本以后需要再安装一下工具,命令如下: npm install -g express-generator

  2. CentOS 7 安装 MySQL

    转自:http://www.centoscn.com/mysql/2016/0315/6844.html 环境 CentOS 7.1 (64-bit system) MySQL 5.6.24 Cent ...

  3. freeregex-0.01 使用文档

    -- freeregex,简化字符串处理 freeregex使用大体分为两个部分: 正则确定 功能操作 正则确定:共有EMAIL.IP等静态属性:anyOf(String regex)静态方法 :和o ...

  4. ---JS canvas学习笔记

    context的fillStyle属性 fillStyle=color | gradient | image | canvas |video strokeStyle也有上述属性. 1.color:#f ...

  5. NOT IN查询效率低,用它的等效写法提高效率。

    最近在处理大数据量导入的时候,使用OPENROWSET将Excel导入到临时表中之后,需要对数据进行唯一性验证.这时候发现使用NOT IN严重影响效率,一条sql可能执行10分钟甚至更久.尝试改变写法 ...

  6. VS2010+C#+在新建类或接口时在文件开头自动生成作者和日期等备注

    今天在公司项目准备开始,为达到项目的规范管理,要求每个文件的标准日期,作者等信息,搜集了百度的资料,新建文件时效果如下: 其实原理很简单,只要修改VS,IDE文件下的类(或接口)模版代码 文件路径:C ...

  7. zabbix3.0 安装Tips

    原文转自:http://www.cnblogs.com/tae44/p/4812190.html#3270843 此处只能留空,否则,提示安装无法进行!!

  8. LVS_DR模式构建配置

    一.环境准备 lvs负载均衡器 系统:centos6.8 ip:192.168.2.203 vip:192.168.2.17 web服务器RS1 系统:centos6.8 ip:192.168.2.2 ...

  9. 第九章 springboot + mybatis + 多数据源 (AOP实现)(转载)

    本编博客转发自:http://www.cnblogs.com/java-zhao/p/5415896.html 1.ShopDao package com.xxx.firstboot.dao; imp ...

  10. (原创)通用查询实现方案(可用于DDD)[附源码] -- 设计思路

    [声明] 写作不易,转载请注明出处(http://www.cnblogs.com/wiseant/p/3988592.html).   [系列文章] 通用查询实现方案(可用于DDD)[附源码] -- ...