【问题标题】:WCF: Passing Username and password to another service (No Https)WCF:将用户名和密码传递给另一个服务(无 Https)
【发布时间】:2012-07-17 21:11:18
【问题描述】:

我必须创建一个 WCF 服务 (ServiceWrapper),它引用另一个 WCF 服务 (RealService)。

我希望 ServiceWrapper 的客户在身份验证请求中传递用户名/密码。

ServiceWrapper调用RealService的操作。我需要将收到的用户名/密码传递给 RealSerivce 进行身份验证,然后调用其操作。

我需要在 Http 而不是 Https(SSL/TLS) 上托管服务。

问题:如何在不使用 Https(SSL/TLS) 的情况下,使用服务接收到的客户端凭据向引用的服务进行身份验证?

【问题讨论】:

  • 问题:如何在不使用 Https(SSL/TLS) 的情况下,使用服务接收到的客户端凭据向引用的服务进行身份验证?

标签: c# .net wcf wcf-security wcf-authentication


【解决方案1】:

您可以使用 SOAP 安全性。有两种 SecurityMode 适合您 - Message、TransportWithMessageCredential。

  1. 您应该像这样在<binding> 部分配置安全模式(用户名)

    <security mode="TransportWithMessageCredential">
        <transport clientCredentialType="" />
        <message clientCredentialType="UserName" />
    </security>
    
  2. 接下来,您应该在&lt;behavior&gt; 部分指定自定义验证器

    <behavior name="CommonBehavior">
        <serviceMetadata />
        <serviceDebug includeExceptionDetailInFaults="True"/>
        <serviceCredentials>
            <userNameAuthentication userNamePasswordValidationMode="Custom"
                 customUserNamePasswordValidatorType="Megatec.MasterTourService.CustomUserNameValidator, Megatec.MasterTourService"/>
    
            <serviceCertificate findValue="WCFServer" storeLocation="LocalMachine" 
                storeName="My" x509FindType="FindBySubjectName"/>
            <clientCertificate>
                <authentication certificateValidationMode="PeerTrust" />
            </clientCertificate>
        </serviceCredentials>
    </behavior>
    
  3. 在您的自定义验证器中,您可以访问和存储用户名和密码,它们是作为 ServiceWrapper 的信用提供的。

    using System.ServiceModel;
    using System.IdentityModel.Selectors;
    namespace MyService
    {
        public class CustomUserNameValidator : UserNamePasswordValidator
        {
            public override void Validate(string userName, string password)
            {
                if (!(userName == "testMan" && password == "pass"))
                    throw new FaultException("Incorrect login or password");
    
                // save your Usermame and Password for future usage.
             }
        }
    }
    
  4. 当您需要访问 RealService 时,您可以使用用户名和密码作为凭据,如下面的示例:

    private readonly Dictionary<Type, Object> channelFactoryDictionary = new Dictionary<Type, Object>();
    private ChannelFactory<T> GetChannelFactory<T>() where T : class
    {
        if (channelFactoryDictionary.Keys.Contains(typeof(T)))
            return channelFactoryDictionary[typeof(T)] as ChannelFactory<T>;
    
        var channelFactory = new ChannelFactory<T>("*");
        channelFactory.Credentials.UserName.UserName = userName;
        channelFactory.Credentials.UserName.Password = password;
    
        channelFactoryDictionary.Add(typeof(T), channelFactory);
    
        return channelFactory;
    }
    

【讨论】:

  • 问题:如何在不使用 Https(SSL/TLS) 的情况下,使用服务接收到的客户端凭据向引用的服务进行身份验证?
  • +1 在您的第 3 步中,我建议将凭据存储在自定义 OperationContext 扩展中。这样,您就可以保证存储的值具有正确的生命周期(服务调用的持续时间)。有一个example here
【解决方案2】:

如果 SSL 不是一个选项,您将需要使用 SOAP 消息安全性 (SecurityMode = Message)。

http://msdn.microsoft.com/en-us/library/ms733137.aspx

【讨论】:

    猜你喜欢
    • 2015-11-11
    • 2013-04-08
    • 1970-01-01
    • 1970-01-01
    • 2011-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多