为简单的 WCF 服务打开基本身份验证?

Posted

技术标签:

【中文标题】为简单的 WCF 服务打开基本身份验证?【英文标题】:Turn on Basic Authentication for a simple WCF service? 【发布时间】:2015-01-22 16:01:33 【问题描述】:

我有一个非常简单的 WCF Web 服务,客户在他们自己的 IIS 上托管。

客户拥有自己的客户端,他们一直在测试环境中对其进行测试,并且一切正常,直到他们禁用匿名身份验证并启用基本身份验证。一旦他们这样做了,他们就会开始出错:

The authentication schemes configured on the host ('Basic') do not allow those configured on the binding 'BasicHttpBinding' ('Anonymous'). Please ensure that the SecurityMode is set to Transport or TransportCredentialOnly. 

那么,我需要做什么才能使基本身份验证正常工作?

我的网络服务当前的web.config

<configuration>
    <system.web>
        <compilation debug="true" targetFramework="4.5" />
        <httpRuntime targetFramework="4.5" />
    </system.web>
    <system.serviceModel>
        <behaviors>
            <serviceBehaviors>
                <behavior name="">
                    <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
                    <serviceDebug includeExceptionDetailInFaults="false" />
                </behavior>
            </serviceBehaviors>
        </behaviors>
        <serviceHostingEnvironment aspNetCompatibilityEnabled="true"
            multipleSiteBindingsEnabled="true" />
    </system.serviceModel>
</configuration>

我有自己的测试客户端,可以针对我的网络服务运行。它的当前app.config

<configuration>
    <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
    <system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="BasicHttpBinding_IMyServiceSvc" />
            </basicHttpBinding>
        </bindings>
        <client>
            <endpoint address="http://localhost/MyServiceSvc.svc"
                binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IMyServiceSvc"
                contract="MyServiceSvc.IMyServiceSvc"
                name="BasicHttpBinding_IMyServiceSvc" />
        </client>
    </system.serviceModel>
</configuration>

当我在本地 IIS 上安装服务并针对它运行客户端时,一切正常,启用了匿名身份验证。

我需要做什么才能在 IIS 中打开基本身份验证,并将客户端和服务器都配置为使用基本身份验证?

我当前的测试客户端代码:

public class BlackHillsCompletionSvcTest

    static void Main(string[] args)
    
        using (var client = new MyServiceSvcClient())
        
            var data = new Data
            
                id = "1",
                description = "test data"
            ;

            try
            
                var result = client.receiveData(data);
            
            catch (Exception ex)
            
                var msg = ex.Message;
            
        
    

==尝试次数:==

根据 Pankaj Kapare 的建议,我将此添加到 web 服务的 web.config

<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="httpBinding">
                <security mode="TransportCredentialOnly">
                    <transport clientCredentialType="Basic" />
                </security>
            </binding>
        </basicHttpBinding>
    </bindings>
    ...
</system.serviceModel>

这样,我在创建客户端时出错:

The binding at system.serviceModel/bindings/basicHttpBinding does not have a configured binding named 'BasicHttpBinding_IMyServiceSvc'. This is an invalid value for bindingConfiguration. 

所以我将此添加到客户的app.config

<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="BasicHttpBinding_IMyServiceSvc">
                <security mode="TransportCredentialOnly">
                    <transport clientCredentialType="Basic" />
                </security>
            </binding>
        </basicHttpBinding>
    </bindings>
    ...
</system.serviceModel>

这样,我又遇到了一个错误:

The username is not provided. Specify username in ClientCredentials.

所以我在我的客户端中添加了用户名和密码:

using (var client = new MyServiceSvcClient())

    client.ClientCredentials.UserName.UserName = "myusername";
    client.ClientCredentials.UserName.Password = "mypassword";
    ...

然后,我又遇到了另一个错误:

The requested service, 'http://localhost/MyServiceSvc.svc' could not be activated.  Which got me wondering. So I loaded the .svc page in my browser, was asked to log in, and after I did, I saw this:

The authentication schemes configured on the host ('Basic') do not allow those configured on the binding 'BasicHttpBinding' ('Anonymous').  Please ensure that the SecurityMode is set to Transport or TransportCredentialOnly.  Additionally, this may be resolved by changing the authentication schemes for this application through the IIS management tool, through the ServiceHost.Authentication.AuthenticationSchemes property, in the application configuration file at the <serviceAuthenticationManager> element, by updating the ClientCredentialType property on the binding, or by adjusting the AuthenticationScheme property on the HttpTransportBindingElement.

客户看到的是什么。

想法?

== 也许是一个解决方案? ==

我认为可能缺少的是服务器上的服务定义,将绑定绑定到端点:

<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="httpBinding">
                <security mode="TransportCredentialOnly">
                    <transport clientCredentialType="Basic" />
                </security>
            </binding>
        </basicHttpBinding>
    </bindings>
    <services>
        <service
                name="MyServiceSvcNs.MyServiceSvc"
                behaviorConfiguration="ServiceWithMetaData"
                >
            <endpoint name="Default"
                address=""
                binding="basicHttpBinding"
                bindingConfiguration="httpBinding"
                contract="MyServiceSvcNs.IMyServiceSvc"
                />
        </service>
    </services>
    <behaviors>
        <serviceBehaviors>
            <behavior name="ServiceWithMetaData">
                <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
                <serviceDebug includeExceptionDetailInFaults="false" />
            </behavior>
        </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"
        multipleSiteBindingsEnabled="true" />
</system.serviceModel>

有了这个,事情似乎开始了。至少乍一看。

【问题讨论】:

【参考方案1】:

好的,我想通了。

首先,在 IIS 管理器中,您需要关闭匿名身份验证,并打开基本身份验证。这可能需要先启用基本身份验证,然后重新启动 IIS 管理器。这是基本的 IIS 内容,并不是我的问题的一部分。

然后,我们需要对 Web 服务的 web.config 进行更改。如果你记得,它看起来像这样:

<configuration>
    <system.web>
        <compilation debug="true" targetFramework="4.5" />
        <httpRuntime targetFramework="4.5" />
    </system.web>
    <system.serviceModel>
        <behaviors>
            <serviceBehaviors>
                <behavior name="">
                    <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
                    <serviceDebug includeExceptionDetailInFaults="false" />
                </behavior>
            </serviceBehaviors>
        </behaviors>
        <serviceHostingEnvironment aspNetCompatibilityEnabled="true"
            multipleSiteBindingsEnabled="true" />
    </system.serviceModel>
</configuration>

我们需要将其更改为:

<configuration>
    <system.web>
        <compilation debug="true" targetFramework="4.5" />
        <httpRuntime targetFramework="4.5" />
    </system.web>
    <system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="httpTransportCredentialOnlyBinding">
                    <security mode="TransportCredentialOnly">
                        <transport clientCredentialType="Basic" />
                    </security>
                </binding>
            </basicHttpBinding>
        </bindings>
        <services>
            <service
                    name="MyServiceSvcNs.MyServiceSvc"
                    behaviorConfiguration="ServiceWithMetaData"
                    >
                <endpoint name="Default"
                    address=""
                    binding="basicHttpBinding"
                    bindingConfiguration="httpTransportCredentialOnlyBinding"
                    contract="MyServiceSvcNs.IMyServiceSvc"
                    />
            </service>
        </services>
        <behaviors>
            <serviceBehaviors>
                <behavior name="ServiceWithMetaData">
                    <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
                    <serviceDebug includeExceptionDetailInFaults="false" />
                </behavior>
            </serviceBehaviors>
        </behaviors>
        <serviceHostingEnvironment aspNetCompatibilityEnabled="true"
            multipleSiteBindingsEnabled="true" />
    </system.serviceModel>
</configuration>

我们正在做的是定义一个具有 TransportCredentialOnly 安全性的 basicHttpBinding。然后我们定义一个服务,其端点使用该绑定。

然后在客户端,我们有:

<configuration>
    <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
    <system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="BasicHttpBinding_IMyServiceSvc" />
            </basicHttpBinding>
        </bindings>
        <client>
            <endpoint address="http://localhost/MyServiceSvc.svc"
                binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IMyServiceSvc"
                contract="MyServiceSvc.IMyServiceSvc"
                name="BasicHttpBinding_IMyServiceSvc" />
        </client>
    </system.serviceModel>
</configuration>

这需要改为:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
    <system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="httpTransportCredentialOnlyBinding">
                    <security mode="TransportCredentialOnly">
                        <transport clientCredentialType="Basic" />
                    </security>
                </binding>
            </basicHttpBinding>
        </bindings>
        <client>
            <endpoint
                address="http://localhost/MyServiceSvc.svc"
                binding="basicHttpBinding"
                bindingConfiguration="httpTransportCredentialOnlyBinding"
                contract="MyServiceSvc.IMyServiceSvc"
                name="BasicHttpBinding_IMyServiceSvc"
                />
        </client>
    </system.serviceModel>
</configuration>

在这里,我们再次创建一个具有 TransportCredentialOnly 安全性的 basicHttpBinding,我们正在修改端点以使用它。

【讨论】:

【参考方案2】:

在服务 web.config 中配置你的 basicHttpBinding 如下

<bindings>
  <basicHttpBinding>
    <binding name="httpBinding">
      <security mode="TransportCredentialOnly">
        <transport clientCredentialType="Basic" />
      </security>
    </binding>
  </basicHttpBinding>
</bindings>

【讨论】:

如果我将它添加到 web、config 并启用匿名身份验证,一切正常,如果我禁用匿名身份验证并启用基本身份验证,我会收到 MessageSecurityException:“HTTP 请求未经客户端授权身份验证方案“匿名”。从服务器收到的身份验证标头是“基本领域 =“本地主机”。”带有内部异常“远程服务器返回错误:(401)未经授权。” 您是否在请求中发送用户名和密码?您可以发布您的客户端代码吗? 没有。我现在。还是行不通。查看对我原始帖子的修改。 有了我的配置并在客户端设置了用户名/密码,您需要再做一项更改,即 bindingConfiguration="BasicHttpBinding_IMyServiceSvc" 到 bindingConfiguration="httpBinding"。除非你需要 https,否则不要使用 mode="Transport"。 仍然看到“无法激活请求的服务,'localhost/MyServiceSvc.svc'。”

以上是关于为简单的 WCF 服务打开基本身份验证?的主要内容,如果未能解决你的问题,请参考以下文章

如何禁用 WCF 数据服务的身份验证方案

无法使用 WCF 调用具有基本身份验证的 Web 服务

如何对 WCF 4 RESTful 服务进行身份验证?

WCF WebHttp 混合身份验证(基本和匿名)

WCF 和 AD LDS 以及基本身份验证

如何在 WCF 4.0 REST 服务上启用基本身份验证?