【问题标题】:How to authenticate in WCF services in BasicHttpBinding?如何在 BasicHttpBinding 中的 WCF 服务中进行身份验证?
【发布时间】:2010-12-19 18:04:42
【问题描述】:

我正在使用 basicHttpBinding 开发 WCF 服务,这些服务应该可以使用 .net 1.1 和 .net 2.0 访问,为此我使用 basicHttpBinding
在旧的 ASMX Web 服务中,我使用一个 Soap 标头 (AuthHeader) 来对每个请求的用户进行身份验证。

如何在 WCF 中使用 basicHttpBinding 进行身份验证? strong> 任何示例或教程都会有所帮助。


nRk

【问题讨论】:

    标签: wcf wcf-security basichttpbinding wcf-authentication


    【解决方案1】:

    您可以像切换到 WCF 之前一样使用 AuthHeader。也许这对你来说会更方便,因为原则将保持不变。 我在这个解决方案中看到的坏事是纯文本密码传输。无论如何,这只是另一种选择,您可以以某种方式加密/解密密码。

    在这种情况下,您应该实现自己的 IDispatchMessageInspector 和 IClientMessageInspector,例如

    [AttributeUsage(AttributeTargets.Class)]
    public class CredentialsExtractorBehaviorAttribute : Attribute, IContractBehavior, IDispatchMessageInspector
    {
        #region IContractBehavior implementation.
    
        public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint,
                                          DispatchRuntime dispatchRuntime)
        {
            dispatchRuntime.MessageInspectors.Add(this);
        }
    
        ... empty interface methods impl skipped ...
    
        #endregion
    
        #region IDispatchMessageInspector implementation.
    
        public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
        {
            int i = request.Headers.FindHeader("username", "sec");
            if (-1 != i)
            {
                string username = request.Headers.GetHeader<string>("username", "sec");
                ... do smth ...
            }
            return null;
        }
    
        public void BeforeSendReply(ref Message reply, object correlationState)
        {
            return;
        }
    
        #endregion
    }
    

    在一个示例中,我只放置了用户名,但您可以实现一个包含用户名和密码的类,并使用它而不是字符串。 在客户端:

    internal class CredentialsInserter : IContractBehavior, IClientMessageInspector
    {
        private string m_username;
    
        public CredentialsInserter(string username)
        {
            m_username = username;
        }
    
        #region IContractBehavior implementation.
    
        ... empty interface methods impl skipped ...
    
        public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint,
                                        ClientRuntime clientRuntime)
        {
            clientRuntime.MessageInspectors.Add(this);
        }
    
        #endregion
    
        #region IClientMessageInspector implementation.
    
        public object BeforeSendRequest(ref Message request, IClientChannel channel)
        {
            MessageHeader<string> mh = new MessageHeader<string>(m_username);
            request.Headers.Add(mh.GetUntypedHeader("username", "sec"));
            return null;
        }
    
        public void AfterReceiveReply(ref Message reply, object correlationState)
        {
            return;
        }
    
        #endregion
    }
    

    那么你应该将属性 CredentialsExtractorBehaviorAttribute 放在你的服务实现类上。

    [CredentialsExtractorBehavior]
    public class DummyService : IDummyService
    {
       ... impl ...
    }
    

    在客户端,您应该执行以下操作:

            using (DummyServiceClient c = new DummyServiceClient("TcpEndpoint"))
            {
                c.ChannelFactory.Endpoint.Contract.Behaviors.Add(
                    new CredentialsInserter("_username_"));
                c.DummyMethod();
            }
    

    【讨论】:

      【解决方案2】:

      首先 - 是的,你可以!这取决于您是使用传输绑定还是消息绑定 - 如果您面向 Internet,则更有可能使用基于消息的安全性。

      不幸的是,对于基于消息的安全性,basicHttpBinding 只支持证书,这有点麻烦。

      另一方面,wsHttpBinding 也将支持用户名/密码或其他方法。

      您将使用用户名/密码客户端凭据配置 wsHttpBinding,而不是基于消息的安全性,如下所示:

        <system.serviceModel>
          <bindings>
            <wsHttpBinding>
              <binding name="wsUserName">
                <security mode="Message">
                  <message clientCredentialType="UserName"/>
                </security>
              </binding>
            </wsHttpBinding>
          </bindings>
          <services>
            <service name="yourservice">
              <endpoint name="YourEndpoint"
                        address=""
                        binding="wsHttpBinding"
                        bindingConfiguration="wsUserName"
                        contract="IYourService" />
            </service>
          </services>
        </system.serviceModel>
      

      &lt;bindings&gt; 下的部分为 wsHttpBinding 定义了一个绑定配置,该配置使用带有用户名/密码客户端凭据的消息安全性。

      &lt;service&gt; 下的部分定义了一个使用 wsHttpBinding 并引用我们刚刚定义的绑定配置的示例服务。

      在服务器端,您现在可以使用通过网络发送的用户名/密码来验证您的呼叫者,无论是在您的 Active Directory(每个呼叫者都需要您的 AD 帐户)中,还是在 ASP.NET 会员系统中数据库;或者如果你真的需要,你也可以编写自己的身份验证机制。

      在 WCF security at Codeplex 上找到很多有用的信息 - 极好的资源。

      【讨论】:

      • 谢谢,marc_s,我将通过 codeplex 材料。因此,我只能针对 basicHttpBiding 中的证书进行验证。这意味着我无法根据用户名和密码验证用户? basichttpBiding 中是否还有其他方法可以针对用户名和密码进行验证/验证? -- nrk
      • @nrk: 是的,如果你在basicHttpBinding中使用message-security,你只能使用证书进行身份验证。如果您要使用传输安全性,那么您可以使用其他身份验证方式
      【解决方案3】:

      检查场景here 以尝试将其与您的情况相匹配。每个场景都提供了实施解决方案所需的项目清单。

      【讨论】:

        猜你喜欢
        • 2014-07-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-29
        • 2010-12-30
        • 1970-01-01
        • 2023-04-07
        相关资源
        最近更新 更多