客户端身份验证方案“匿名”的 HTTP 请求未经授权?

Posted

技术标签:

【中文标题】客户端身份验证方案“匿名”的 HTTP 请求未经授权?【英文标题】:The HTTP request is unauthorized with client authentication scheme 'Anonymous'? 【发布时间】:2012-10-27 08:16:01 【问题描述】:

在尝试从我的 Web 客户端应用程序调用 RESTful 服务(我已将此示例中的 UserNameAuthenticator 用于 RESTful 服务 Adding basic HTTP auth to a WCF REST service)时,我收到了类似

的错误
The HTTP request is unauthorized with client authentication scheme 'Anonymous'. The authentication header received from the server was 'Basic Realm'.

客户端 CS 代码

BasicHttpBinding binding = new BasicHttpBinding();
binding.SendTimeout = TimeSpan.FromSeconds(25);
binding.Security.Transport.ClientCredentialType =
HttpClientCredentialType.Basic;
EndpointAddress address = new  EndpointAddress("http://localhost:12229/RestServiceImpl.svc");
ChannelFactory<RestService.IRestServiceImpl> factory =
new ChannelFactory<RestService.IRestServiceImpl>(binding, address);
RestService.IRestServiceImpl channel = factory.CreateChannel();
channel.GetStudent();

客户端 Web.config

<system.serviceModel>
    <services>
      <service name="RestService.RestServiceImpl">
        <endpoint address="http://localhost:12229/RestServiceImpl.svc"
          binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_ExternalSystemsService_v1Interface"
          contract="RestService.IRestServiceImpl"
          name="ExternalSystemsService_v1Port" />
      </service>
    </services>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBinding_ExternalSystemsService_v1Interface"
                         closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00"
                         sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false"
                         hostNameComparisonMode="StrongWildcard" maxBufferSize="65536"
                         maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                         messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
                         useDefaultWebProxy="true">
          <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
              maxBytesPerRead="4096" maxNameTableCharCount="16384" />
          <security mode="TransportCredentialOnly">
            <transport clientCredentialType="None" proxyCredentialType="None"
                realm="" />
            <message clientCredentialType="UserName" algorithmSuite="Default" />
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
  </system.serviceModel>

和 RESTful 服务 Web.config

 <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="webHttpTransportSecurity">
          <security mode="TransportCredentialOnly">
            <transport clientCredentialType="None" proxyCredentialType="None" realm="" />
            <message clientCredentialType="UserName" algorithmSuite="Default" />
          </security>
          </binding>
      </basicHttpBinding>
    </bindings>
    <services>
      <service name="RestService.RestServiceImpl">
        <endpoint name="ExternalSystemsService_v1Port" address="" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_ExternalSystemsService_v1Interface" contract="RestService.IRestServiceImpl"></endpoint>
      </service>
    </services>
    <behaviors>
      <endpointBehaviors>
        <behavior>
          <webHttp />
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="SecureRESTSvcTestBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="false" />
          <serviceDebug includeExceptionDetailInFaults="true" />
          <serviceCredentials>
            <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="RESTfulSecuritySH.CustomUserNameValidator, RESTfulSecuritySH" />
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>

有什么建议吗?

【问题讨论】:

在构造BasicHttpBinding 时根本没有使用.config。因此,对于 Auth,您所做的只是设置身份验证协议,但您还没有设置要进行身份验证的凭据。使用将绑定名称作为stringChannelFactory 构造函数,或者在您的实例化BasicHttpBinding 中设置您的凭据。 【参考方案1】:

让我印象深刻的一件事是,在您的客户端 CS 代码中,您以编程方式设置 transport 的 客户端凭据类型:

binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;

但在客户端和服务器配置文件中,您都设置了 message 客户端凭据类型。请注意传输元素的 clientCredentialType 属性是如何设置为“None”的,而消息元素的 clientCredentialType 是如何设置为“UserName”的:

<transport clientCredentialType="None" proxyCredentialType="None" realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />

我总是尝试在开发过程中关闭安全性,然后再慢慢将其重新打开。

这也是一个新的开发项目吗?我很好奇您为什么要使用 WCF over ASP.NET Web API 来提供 RESTful 服务。

【讨论】:

.config 将被完全忽略,因为 OP 自己实例化了 BasicHttpBinding,而不是使用 ChannelFactory 的默认构造函数中的工厂方法。

以上是关于客户端身份验证方案“匿名”的 HTTP 请求未经授权?的主要内容,如果未能解决你的问题,请参考以下文章

异常 = HTTP 请求未经客户端身份验证方案“匿名”授权

HTTP 请求未经客户端身份验证方案“匿名”授权。从服务器收到的身份验证标头是“默认”。

HTTP 请求未经客户端身份验证方案“匿名”授权。从服务器收到的身份验证标头是“基本领域”

WCF-TransportWithMessageCredential HTTP 请求未经授权,客户端身份验证方案“匿名”

未经授权的客户端身份验证方案“匿名”和 URI 方案“https”无效;预期的“http”

HTTP 请求未经客户端身份验证方案“Ntlm”授权