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 一般有兩個, PrimaryKey
和 SecondaryKey
,任意一個都可用。 兩個的目的是方便定期更換密鑰,建議使用 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 發送消息, 可以指定 sr
為 sb://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 處獲得。