如何在 BasicHttpBinding 中的 WCF 服务中进行身份验证?

发布于 2024-08-12 09:11:23 字数 300 浏览 11 评论 0原文

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

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


nRk

I am developing WCF services with basicHttpBinding, these services should be accessible using .net 1.1 & .net 2.0, for this purpose I am using basicHttpBinding.
In old ASMX web services I assed one Soap Header (AuthHeader) to authenticate the user every request.

How Can I authenticate in WCF using basicHttpBinding? Any sample Or tutorial will helpfull.

nRk

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

送舟行 2024-08-19 09:11:24

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

不幸的是,对于基于消息的安全性,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>

下的部分为使用消息的 wsHttpBinding 定义了绑定配置用户名/密码客户端凭据的安全性。

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

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

查找有关 WCF Codeplex 安全性 的大量有用信息 -优秀的资源。

First of all - yes you can! It depends on whether you use Transport or Message binding - if you're internet-facing, you're more likely to use message-based security.

Unfortunately, for message-based security, basicHttpBinding only supports certificates which is a bit of a pain.

wsHttpBinding on the other hand would support username/password or other methods as well.

You'd configure wsHttpBinding with username/password client credentials over message-based security like this:

  <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>

The section under <bindings> defines a binding configuration for wsHttpBinding that uses message-security with username/password client credentials.

The section under <service> defines a sample service that uses wsHttpBinding and that references that binding configuration that we just defined.

On the server side, you could now use the username/password that's being sent over the wire to validate your callers either in your Active Directory (everyone calling needs an AD account with you), or in the ASP.NET membership system database; or if you really really must, you could write your own authentication mechanism, too.

Find a lot of useful information on WCF security at Codeplex - excellent resource.

吃兔兔 2024-08-19 09:11:24

请在此处查看场景,尝试将其中一个与您的情况相匹配。每个场景都提供了实施解决方案所需的项目检查列表。

Check the scenarios here to try to match one to your situation. Each scenario is provided with a chceklist of items required to implement the solution.

浅忆 2024-08-19 09:11:23

您可以像切换到 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();
        }

You can use AuthHeader as you did before switching to WCF. Maybe it will be more convinient for you, cause the princples will remain the same.
The bad thing i see in this solution is a plain text password transfer. Anyway, it's just another option and you can encrypt/decrypt the password somehow.

In this case you should implement your own your IDispatchMessageInspector & IClientMessageInspector, like

[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
}

In a sample i placed to header only username, but you can implement your a class containing username and password and use it instead of string.
On the client:

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
}

Then you should place attribute CredentialsExtractorBehaviorAttribute on your service implementation class.

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

And on the client side you should do the following:

        using (DummyServiceClient c = new DummyServiceClient("TcpEndpoint"))
        {
            c.ChannelFactory.Endpoint.Contract.Behaviors.Add(
                new CredentialsInserter("_username_"));
            c.DummyMethod();
        }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文