4

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

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


nRk

4

3 回答 3

7

您可以像切换到 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();
        }
于 2009-12-18T10:05:45.720 回答
3

首先 - 是的,你可以!这取决于您是使用传输绑定还是消息绑定 - 如果您面向 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>

下面的部分<bindings>定义了wsHttpBinding 的绑定配置,该配置使用带有用户名/密码客户端凭据的消息安全性。

下面的部分<service>定义了一个使用 wsHttpBinding 并引用我们刚刚定义的绑定配置的示例服务。

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

在 Codeplex找到很多关于 WCF 安全性的有用信息 - 极好的资源。

于 2009-11-24T05:40:32.467 回答
0

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

于 2009-12-03T15:52:53.073 回答