WCF .net 4.0 HTTP 基本身份验证

Posted

技术标签:

【中文标题】WCF .net 4.0 HTTP 基本身份验证【英文标题】:WCF .net 4.0 HTTP Basic Authentication 【发布时间】:2011-08-17 21:04:31 【问题描述】:

我已经为此搜索了几天。

我只是想使用基本 HTTP 身份验证将用户名/密码传递到我的 RESTful 服务中。其他一切都很棒!

这是我的 web.config 的样子:

<?xml version="1.0"?>
<configuration>

  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>

  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true">
      <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
    </modules>
  </system.webServer>

  <system.serviceModel>

    <bindings>
      <wsHttpBinding>
        <binding name="">
          <security mode="Message">
            <message clientCredentialType="UserName" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>

    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>

    <standardEndpoints>
      <webHttpEndpoint>
        <!-- 
            Configure the WCF REST service base address via the global.asax.cs file and the default endpoint 
            via the attributes on the <standardEndpoint> element below
        -->
        <standardEndpoint name="" helpEnabled="true" defaultOutgoingResponseFormat="Json" automaticFormatSelectionEnabled="true"/>
      </webHttpEndpoint>
    </standardEndpoints>

    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceCredentials>
            <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="ParkingPandaREST.CustomUserNameValidator, ParkingPandaREST" />
          </serviceCredentials>      
        </behavior>
      </serviceBehaviors>
    </behaviors>


  </system.serviceModel>

</configuration>

然后我创建了一个 CustomUserNameValidator 类,它具有以下内容:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace ParkingPandaREST

    public class CustomUserNameValidator : System.IdentityModel.Selectors.UserNamePasswordValidator
    
        // This method validates users. It allows in two users, test1 and test2 
        // with passwords 1tset and 2tset respectively.
        // This code is for illustration purposes only and 
        // must not be used in a production environment because it is not secure.    
        public override void Validate(string userName, string password)
        
            if (null == userName || null == password)
            
                throw new ArgumentNullException();
            

            if (!(userName == "test1" && password == "1tset") && !(userName == "test2" && password == "2tset"))
            
                // This throws an informative fault to the client.
                throw new System.ServiceModel.FaultException("Unknown Username or Incorrect Password");
                // When you do not want to throw an infomative fault to the client,
                // throw the following exception.
                // throw new SecurityTokenException("Unknown Username or Incorrect Password");
            
        
    

我只是在我的本地机器上运行该服务并尝试在 CustomUserNameValidator 类中打断点,但它永远不会到达那里。所以我现在没有使用 SSL,只是试图获取正在传递的用户名/密码。

【问题讨论】:

【参考方案1】:

这是我想出的答案。它可能需要稍作调整,但它是您完成工作所需的核心。

注意:在 IIS 中关闭基本身份验证

           // Get the Header Authorization Value
            string headerValue = operationContext.IncomingRequest.Headers[HttpRequestHeader.Authorization];
            headerValue = headerValue.Replace("Basic ", "");
            headerValue = DecodeBase64String(headerValue);

            // Get Username and Password
            string userName = headerValue.Substring(0, headerValue.IndexOf(":"));
            string password = headerValue.Substring(headerValue.IndexOf(":") + 1, headerValue.Length - userName.Length - 1);

            // Do Custom Authorization here with the userName and password

.......

这里还有 DecodeBase64String 函数

    public static string DecodeBase64String(string encodedData)
    
        byte[] encodedDataAsBytes = System.Convert.FromBase64String(encodedData);
        string returnValue = System.Text.ASCIIEncoding.ASCII.GetString(encodedDataAsBytes);
        return returnValue;
    

希望能帮助遇到同样问题的其他人 - 干杯!

【讨论】:

我还是建议使用 Encoding.UTF8.GetString(encodedData)【参考方案2】:

基本身份验证是一种 HTTP 协议。因此,它是传输安全,而不是消息安全。你的配置应该包含这个 sn-p:

<security mode="Transport">
    <transport clientCredentialType="Basic" />
</security>

但即使您做对了,您的自定义代码也可能不会被调用。您可以在 blog 中找到有关此问题的更多详细信息。

【讨论】:

为了处理我使用的服务的基本身份验证:altairiswebsecurity.codeplex.com 我将我的服务托管为 MVC 控制器而不是 WCF。 因此,使用全新版本的 WCF,您无法正确执行基本 HTTP 身份验证...哇,这太可怕了! @Codo 无法关注您的博客链接 :( 我的自定义验证器没有执行同样的问题【参考方案3】:

WCF 4 中 HTTP 传输的默认绑定是 basicHttpBinding。如果您将 wsHttpBinding 元素转换为 basicHttpBinding 元素并将其配置为进行自定义验证,那么您的代码应该会执行。

【讨论】:

我只是尝试将 更改为 ,但仍然无法使其达到断点。我还有什么遗漏吗? 可能是您的客户端配置和服务配置不同步。此外,您需要配置 IIS 以允许 HTTP 基本身份验证。 IIS 配置因版本而异,但这里是 IIS 7 配置:technet.microsoft.com/en-us/library/cc772009(WS.10).aspx 那么这不会在我使用 VS2010 的本地开发人员机器上运行 - 只需按 F5 并使其处于调试模式吗? 我还没有尝试使用内置的 Visual Studio 开发 Web 服务器来执行此操作。如果服务项目是 WCF 服务应用程序,那么您应该能够进入项目属性选项卡,并且在 Web 选项卡中有一个使用本地 IIS 服务器的选项。 VS 会自动为该服务创建一个网站。设置完成后,将本地 IIS 配置为基本 HTTP 身份验证。 F5 将照常在此模式下工作。至少这就是我过去所做的:) 您能够使用自定义 HTTP 基本身份验证吗?没有这个问题:samuelotter.com/blog/2010/07/…

以上是关于WCF .net 4.0 HTTP 基本身份验证的主要内容,如果未能解决你的问题,请参考以下文章

如何在 RESTful WCF API 中实现 HMAC 身份验证

完整 .NET 和 .NET Core 之间的 WCF 基本身份验证

无法使用 WCF 调用具有基本身份验证的 Web 服务

在 WCF 服务中使用 ASP.NET 成员资格提供程序身份验证

WCF 4.0 REST 用户名密码认证

表单身份验证、ASP.NET MVC 和 WCF RESTful 服务