安全性

应用到: Service Bus for Windows Server 1.0

在 Azure 和 Windows Server 中,Service Bus 都需要访问令牌以授权对其实体的访问。由于 Microsoft Azure Active Directory 访问控制(也称为访问控制服务或 ACS) 在 Windows Server 上不可用,Service Bus for Windows Server 包括一个简单的 Service Bus 安全令牌服务 (SBSTS)。SBSTS 和 Windows 安全模型集成,并可根据 Windows 身份(存储在本地 Windows 身份商店或 Active Directory 中)发布简单 Web 令牌 (SWT)。

Service Bus for Windows Server 配置

SBSTS 是 Service Bus for Windows Server 网关的组成部分,并在每个 Service Bus for Windows Server 场主机上运行。创建 服务命名空间 时初始化 SBSTS 设置。

你可在 Service Bus for Windows Server 中的两个地方指定授权规则:

  1. 在 Service Bus for Windows Server 服务命名空间 级别,管理员指定在所有基础 Service Bus 消息传送实体(队列、主题和订阅)上拥有管理发送接收权限的用户列表。在 服务命名空间 的创建期间,你可向一个安全主体(一个用户或一个安全组)授予这些权限,并可在以后使用 PowerShell 命令修改它们。有关详细信息,请参阅 TechNet 上的 New-SBNamespaceSet-SBNamespace cmdlet。

  2. 在 Service Bus for Windows Server 消息传送实体水平(队列或主题),你可为该实体指定授权规则。管理规则控制用户是否可管理权限以及创建、更改或删除实体。发送规则控制用户是否可向一个 Service Bus for Windows Server 实体发送消息,接收控制用户是否可从 Service Bus for Windows Server 实体接收消息。要为一个实体配置访问权限,管理员必须配置授权规则。此操作需要 服务命名空间 上的管理权限。

然后 服务命名空间 上带有管理权限的用户可向 服务命名空间 中的实体添加授权规则。例如,一旦你创建一个 NamespaceManager 实例,可在创建实体时添加授权规则,或可以在现有实体上修改它们。以下示例在创建一个队列时添加授权规则:

// Example of allowing a domain group manage and send permissions to a queue
QueueDescription sourceQ = new QueueDescription(sourceQName);
string domainGroup = “MyGroup@" + Environment.GetEnvironmentVariable("USERDNSDOMAIN"); 
AuthorizationRule sourceQRule = new AllowRule("owner", RoleClaimType, domainGroup, new List<string>() {"Manage", "Send" });
sourceQ.Authorization.Add(sourceQRule );

// Example of granting a domain user listen permissions to a queue
string domainUser = “MyUserName@" + Environment.GetEnvironmentVariable("USERDNSDOMAIN");
AuthorizationRule ListenRule = new AllowRule("owner", IdentityClaimType, domainUser, new List<string>() { "Listen" });
sourceQ.Authorization.Add(ListenRule);
namespaceManager.CreateQueue(sourceQ);

上一个示例使用两个授权规则创建一个队列 (sourceQ):授权组 (MYGroup) 管理和发布权限,并授权用户 (MyUserName) 侦听权限。

访问 Service Bus for Windows Server

访问一个 服务命名空间 或 Service Bus for Windows Server 上的实体的客户端的任何操作必须从 SBSTS 获得一个令牌。

note备注
SBSTS 发布的默认令牌生存期为 20 分钟。

使用 Service Bus for Windows Server SDK。

通过从 STS 获得一个令牌,可获得对 Service Bus 实体的访问权。默认情况下,Service Bus for Windows Server 中使用的 $STS 侦听端口 9355。

使用 Service Bus for Windows Server 的客户端可创建一个令牌提供商,以使用他们的 NamespaceManagerMessagingFactory 类。例如:

stsUris= new List<Uri>() { new Uri(string.Format(CultureInfo.InvariantCulture, 
    "sb://{0}:9355/", <hostname>)) };
TokenProvider tokenProvider = TokenProvider.CreateWindowsTokenProvider(stsUris);

string runtimeAddress = string.Format("sb://{0}:9354/{1}/", <hostname>,  
    <serviceNamespace>);
MessagingFactory messagingFactory = MessagingFactory.Create(runtimeAddress, 
    new MessagingFactorySettings() { TokenProvider = this.tokenProvider, 
    OperationTimeout = TimeSpan.FromMinutes(30) });

在上一示例中,用托管 Service Bus for Windows Server 的服务器名称取代 <hostname>。用你希望访问的 服务命名空间 的名称取代 <serviceNamespace>

使用 MessagingFactory 的后续操作自动通过 TokenProvider 对象获得令牌,并将它包括在所有操作中。此类别也根据令牌到期时间管理令牌缓存和续订。

使用 HTTP

以下示例介绍从 SBSTS 使用 HTTP 的访问令牌获取,它驻留在 $STS 地址。

public static void Usage()
{
    string token = GetOAuthAccessToken(new 
        Uri("https://<hostname.domain.com>:9355/<namespace> /"), 
        "user@corp.domain. com", "<password>", TimeSpan.FromMinutes(10)); 
}

public static string GetOAuthAccessToken(Uri namespaceBaseAddress, string userName, string userPassword, TimeSpan timeout)
{
    const int ServicePointMaxIdleTimeMilliSeconds = 50000;
    const string OAuthTokenServicePath = "$STS/OAuth/";
    const string ClientPasswordFormat = 
        "grant_type=authorization_code&client_id={0}&client_secret={1}&scope={2}";

    Uri requestUri = new Uri(namespaceBaseAddress, OAuthTokenServicePath);
    string requestContent = string.Format(CultureInfo.InvariantCulture, 
        ClientPasswordFormat, HttpUtility.UrlEncode(userName), 
        HttpUtility.UrlEncode(userPassword), 
        HttpUtility.UrlEncode(namespaceBaseAddress.AbsoluteUri));
    byte[] body = Encoding.UTF8.GetBytes(requestContent);

    HttpWebRequest request = WebRequest.Create(requestUri) as HttpWebRequest;
    request.ServicePoint.MaxIdleTime = ServicePointMaxIdleTimeMilliSeconds;
    request.AllowAutoRedirect = true;
    request.MaximumAutomaticRedirections = 1;
    request.Method = "POST";
    request.ContentType = "application/x-www-form-urlencoded";
    request.ContentLength = body.Length;
    request.Timeout = Convert.ToInt32(timeout.TotalMilliseconds, 
        CultureInfo.InvariantCulture);

    using (Stream requestStream = request.GetRequestStream())
    {
        requestStream.Write(body, 0, body.Length);
    }

    string rawAccessToken = null;
    using (var response = request.GetResponse() as HttpWebResponse)
    {
        using (Stream stream = response.GetResponseStream())
        {
            using (var reader = new StreamReader(stream, Encoding.UTF8))
            {
                rawAccessToken = reader.ReadToEnd();
            }
        }
    }

    string simpleWebToken = string.Format(CultureInfo.InvariantCulture, 
        "WRAP access_token=\"{0}\"", rawAccessToken);
    return simpleWebToken;
}

本例中,你可用所示格式替代 hostnamenamespaceusername 值。

在发往 Service Bus for Windows Server 的后续消息中,客户端可将 HTTP 授权标头设置为前一示例中通过调用 GetOAuthAccessToken() 方法获得的令牌。

note备注
使用 HTTP 的客户端负责根据令牌到期时间管理令牌缓存和续订。