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

时间:2022-08-27 22:42:45

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

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中私信&lpar;DLQ - Dead Letter Queue&rpar;如何快速清理

    在博文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 &lpar;3&rpar; 队列&lpar;Queue&rpar; 使用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&period;NET Core中使用Azure Service Bus Queue

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

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

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

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

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

  9. Windows Azure Service Bus &lpar;6&rpar; 中继&lpar;Relay On&rpar; 使用VS2013开发Service Bus Relay On

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

随机推荐

  1. UIButton无法响应点击事件

    一.问题描述 因为项目需要,需要UITableView上添加固定的筛选表头,一直固定,不能随UITableView滚动.所以直接将表头与UITableView分离,将它添加到控制器的UIView上,即 ...

  2. SAP iDoc 概念及管理

    创建IDOC:   第一步:WE31 创建IDOC所包含的字段.   第二步:WE30 创建IDOC 把Segment分配给IDOC   第三步:WE81  创建信息类型   第四步:WE82   把 ...

  3. 戴文的Linux内核专题:08内核配置(4)

    转自Linux中国 这个第四部分里,我们将继续配置更多的设置和特性. 这里我们被问及关于"IBM Calgary IOMMU support (CALGARY_IOMMU)".这个 ...

  4. 简单工厂模式(Simple Factory Pattern)

    简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一.简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例.简单工厂 ...

  5. Fragment 和 FragmentActivity的使用(二)

      今天继续完成剩下的学习部分,现在项目很多地方使用viewpager来提供滑动,今天记录学习viewpager配合fragment的显示,增加一个CallLogsFragment配合之前SMSLis ...

  6. 利用ajax做的柱状图,线性统计图,饼状图

    柱状图,两个不同类型的数据 以下是html页面代码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN&quot ...

  7. 在DOS命令中输入ipconfig &sol;all,出现&OpenCurlyDoubleQuote;该命令不是系统内部命令&period;&period;&period;&period;&period;&period;”

    第一种情况:1.先去C:\Windows\System32下查找有没有 ipconfig.exe的执行文件,有的话说明系统文件没有丢失,否则要去网上下载一个 ipconfig.exe文件,并放到C:\ ...

  8. Redmine 安装、搭建

    参考两个博客: 1.https://blog.csdn.net/g19881118/article/details/59476045 2.https://www.cnblogs.com/chendal ...

  9. linux的越墙方法

    .首先要安装openSSH, Ubuntu缺省没有安装SSH Server,使用以下命令安装: sudo apt-get install openssh-server 但是系统有时候会出现E类错误,无 ...

  10. Vue2键盘事件:keydown&sol;keyup&period;&period;&period;

    Vue2键盘事件:keydown/keyup... 1.使用 <!DOCTYPE html> <html> <head> <title></tit ...