如何为简单的WCF服务启用基本身份验证?

6

我有一个非常简单的WCF webservice,客户正在自己的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. 

那么,我需要做什么才能让基本认证工作?

我的webservice当前的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>

我有自己的测试客户端,可以对我的Web服务进行测试。它当前的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的建议,我将以下内容添加到webservice的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>

这样看起来,事情似乎正在发挥作用。至少乍一看是这样。

2个回答

11

好的,我明白了。

首先,在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,然后修改终结点以使用它。


1

请按以下方式在服务web.config中配置basicHttpBinding

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

如果我将它添加到web.config中,并保留匿名身份验证启用,则可以正常工作。如果我禁用匿名身份验证并启用基本身份验证,则会出现MessageSecurityException:“HTTP请求未经授权,客户端身份验证方案为“ Anonymous”。从服务器接收到的身份验证头是'Basic realm="localhost"'。”,其中包含一个内部异常“远程服务器返回错误:(401) 未经授权”。 - Jeff Dege
1
你是否在请求中发送了用户名和密码?你能发布你的客户端代码吗? - Pankaj Kapare
之前没有,现在有了,但仍然不起作用。请查看我原帖所做的修改。 - Jeff Dege
在我的配置已经就位并在客户端设置了用户名/密码后,您需要进行一项更改,即将bindingConfiguration="BasicHttpBinding_IMyServiceSvc"绑定到bindingConfiguration="httpBinding"。除非需要https,否则不要使用mode="Transport"。 - Pankaj Kapare
您需要在IIS中禁用“匿名”身份验证并启用基本身份验证。 - Pankaj Kapare
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接