65.9K
CodeProject 正在变化。 阅读更多。
Home

Azure 中的 WCF 安全和身份验证 (WsHttpBinding, 使用用户名和密码凭据)

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.33/5 (2投票s)

2016年4月15日

CPOL

2分钟阅读

viewsIcon

21030

如何通过 HTTPS 在 Azure Web 应用中配置 WCF 服务,并进行身份验证,只需几个简单的步骤。

引言

我花费了大量时间研究和调查 Azure 中的 WCF 安全性,但找不到直接在 Azure Web 应用中实现的有效解决方案。有很多关于 WCF 安全性的内容涉及 IIS、Azure 云服务(webrole/webworker),但没有关于 Azure Web 应用程序(或 Web API)的内容。因此,以下是在 Azure Web 应用中设置 HTTPS 和基本身份验证的一些简单步骤,这些步骤对我有效。

操作指南

我们需要处理线路的两端:WCF 服务本身及其客户端

服务

如你可能已经知道,HTTPS 协议需要 SSL 证书。好消息是,Azure *.azurewebsites.net 域名已经由 Microsoft 提供的证书保护。你可以使用 https://mywebsite.azurewebsites.net 安全地访问你的站点。但是,请注意,*.azurewebsites.net 是一个共享域名,与所有共享域名一样,不如使用你自己的证书的自定义域名安全。在 Azure 应用服务中为应用启用 HTTPS 和自定义域名超出了本文的主题范围,你可以在以下资源中找到有用的信息 https://azure.microsoft.com/en-us/documentation/articles/web-sites-configure-ssl-certificate/

Web.config

首先,让我们设置服务器的 web.config

<system.serviceModel>
    <services>
      <service name="MyProject.MyService" behaviorConfiguration="serviceBehavior">
        <endpoint address="https://mywebapi.azurewebsites.net/MyService.svc" binding="wsHttpBinding"
           bindingConfiguration="secureHttpBinding" contract="MyProject.Service.Contracts.IMyService" />
      </service>      
    </services>
    <behaviors xdt:Transform="Replace">
      <serviceBehaviors>
        <behavior name="serviceBehavior">
          <serviceMetadata httpGetEnabled="false" httpsGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="false" />
          <serviceCredentials>
            <userNameAuthentication userNamePasswordValidationMode="Custom" 
                customUserNamePasswordValidatorType="MyNamespace.ClientAuthenticator, MyNamespace" />
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>
      <wsHttpBinding>
        <binding name="secureHttpBinding"
                 hostNameComparisonMode="StrongWildcard"
               receiveTimeout="00:01:00"
               sendTimeout="00:01:00"
               openTimeout="00:01:00"
               closeTimeout="00:01:00"
               maxReceivedMessageSize="2147483647"
               maxBufferPoolSize="524288"
               messageEncoding="Text"
               textEncoding="utf-8"
               bypassProxyOnLocal="false"
               useDefaultWebProxy="true" >
          <security mode="TransportWithMessageCredential">
            <message clientCredentialType="UserName" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
  </system.serviceModel>

这里有一些值得强调的元素

  1. Endpoint 运行在 HTTPS 上(address="https://mywebapi.azurewebsites.net/MyService.svc"
  2. WsHttpBinding endpoint 绑定配置具有 <security> 标签,其中 mode="TransportWithMessageCredential" clientCredentialType="UserName" 因此,服务将期望请求中的客户端凭据。因此,我们启用了 WCF 基本身份验证
  3. ServiceBehavior 通过 ServiceCredentials 进行设置,通过这种方式我们告诉 WCF 使用什么方法来验证客户端的凭据。在我们的例子中,是下面描述的 MyNamespace.ClientAuthenticator.cs 类。
ClientAuthenticator.cs

其次,我们需要一个身份验证器来验证客户端

using System;
using System.Collections.Generic;
using System.Configuration;
using System.IdentityModel.Selectors;
using System.Linq;
using System.ServiceModel;
using System.Web;

namespace MyNamespace
{
    public class ClientAuthenticator: UserNamePasswordValidator
    {
        public override void Validate(string userName, string password)
        {
            if (null == userName || null == password)
            {
                throw new FaultException("Credential arguments are not supplied");
            }

            var appSettings = ConfigurationManager.AppSettings;
            if (!string.Equals(userName, appSettings["basicAuthUser"], StringComparison.OrdinalIgnoreCase) && !string.Equals(password, appSettings["basicAuthPsw"], StringComparison.Ordinal))
            {
                throw new FaultException("Invalid user and/or password");
            }
        }
    }
}

客户端

Web.config
<system.serviceModel>
    <client>
       <endpoint address="https://mywebapi.azurewebsites.net/MyService.svc" binding="wsHttpBinding"
           bindingConfiguration="secureHttpBinding" contract="MyProject.Client.Contracts.IMyService" />      
    </client>
    <bindings>
      <wsHttpBinding>
        <binding name="secureHttpBinding"
                 hostNameComparisonMode="StrongWildcard"
               receiveTimeout="00:01:00"
               sendTimeout="00:01:00"
               openTimeout="00:01:00"
               closeTimeout="00:01:00"
               maxReceivedMessageSize="2147483647"
               maxBufferPoolSize="524288"
               messageEncoding="Text"
               textEncoding="utf-8"
               bypassProxyOnLocal="false"
               useDefaultWebProxy="true" >
          <security mode="TransportWithMessageCredential">
            <message clientCredentialType="UserName" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
  </system.serviceModel>

请注意,无法在 web.config 文件的 <system.serviceModel> 标签中配置客户端凭据,我们需要在代码中进行设置。

提供客户端凭据
PeopleServiceClient client = new PeopleServiceClient();
var appSettings = ConfigurationManager.AppSettings;
client.ClientCredentials.UserName.UserName = appSettings["basicAuthUser"];
client.ClientCredentials.UserName.Password = appSettings["basicAuthPsw"];

结论

就这样,一切就绪,Azure 中的 WCF Web 应用已安全。请记住,客户端也必须通过 HTTPS 运行,才能以正确的方式与 WCF 通信。希望这篇文章能为你节省大量研究这个主题的时间。祝你编程愉快。

历史

  • 2016 年 4 月 16 日:初始版本。
© . All rights reserved.