2011-05-03 115 views
5

我一直在为此搜索几天。WCF .net 4.0 HTTP基本认证

我只是想使用基本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,只是试图让用户名/密码被传入。

回答

4

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

注:关闭基本身份验证在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; 
    } 

希望可以帮助一些人谁有同样的问题 - 欢呼!

+3

相同的问题我建议使用Encoding.UTF8.GetString(encodedData),虽然 – 2011-08-03 08:27:12

+0

你把这个代码在哪里? – jao 2016-09-02 09:13:37

1

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

+0

我只是试图改变,仍然无法让它击中断点。 我是否缺少其他东西? – Adam 2011-05-03 17:54:08

+0

可能是您的客户端配置和服务配置不同步。此外,您需要配置IIS以允许HTTP基本身份验证。 IIS配置将因版本而异,但这里是IIS 7配置:http://technet.microsoft.com/en-us/library/cc772009(WS.10).aspx – 2011-05-03 18:03:27

+0

所以这不适用于我的本地开发人员计算机VS2010 - 刚刚击中F5并将其置于调试模式? – Adam 2011-05-03 18:15:16

0

基本认证是一种HTTP协议。因此它是传输安全性,而不是消息安全性。你的配置应该包含这个片段:

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

但是,即使你得到这个权利,你的自定义代码可能不会被调用。你会在这个blog中找到关于这个问题的更多细节。

+0

为了处理我的服务的基本身份验证,我使用:http://altairiswebsecurity.codeplex.com/我将我的服务托管为MVC控制器而不是WCF。 – 2011-05-03 19:09:14

+0

因此,对于WCF的全新版本,您无法正确执行基本的HTTP身份验证......太糟糕了! – Adam 2011-05-03 19:26:50

+0

@Codo无法跟随您的链接的博客:(我有我的自定义验证程序没有执行 – Dendei 2013-02-25 12:35:42