收到 403 禁止错误。客户端身份验证方案“匿名”禁止 HTTP 请求

Posted

技术标签:

【中文标题】收到 403 禁止错误。客户端身份验证方案“匿名”禁止 HTTP 请求【英文标题】:Getting 403 Forbidden error. The HTTP request was forbidden with client authentication scheme 'Anonymous' 【发布时间】:2011-12-11 05:24:12 【问题描述】:

我遇到的这个问题并没有发生在所有访问我们服务的客户身上,但一致的是,当错误发生时,它发生在少数客户的同一个服务调用上。

以下是异常的详细信息:

System.ServiceModel.Security.MessageSecurityException HTTP 请求 被客户端身份验证方案“匿名”禁止。 System.ServiceModel.Security.MessageSecurityException:HTTP 客户端身份验证方案“匿名”禁止请求。 > ---> System.Net.WebException:远程服务器返回错误:(403)禁止。在 System.Net.HttpWebRequest.GetResponse() 在 System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(时间跨度 超时)---内部异常堆栈跟踪结束---服务器 堆栈跟踪:在 System.ServiceModel.Security.IssuanceTokenProviderBase1.DoNegotiation(TimeSpan timeout) at System.ServiceModel.Security.SspiNegotiationTokenProvider.OnOpen(TimeSpan timeout) at System.ServiceModel.Security.TlsnegoTokenProvider.OnOpen(TimeSpan timeout) at System.ServiceModel.Security.WrapperSecurityCommunicationObject.OnOpen(TimeSpan timeout) at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) at System.ServiceModel.Security.CommunicationObjectSecurityTokenProvider.Open(TimeSpan timeout) at System.ServiceModel.Security.SecurityUtils.OpenTokenProviderIfRequired(SecurityTokenProvider tokenProvider, TimeSpan timeout) at System.ServiceModel.Security.SymmetricSecurityProtocol.OnOpen(TimeSpan timeout) at System.ServiceModel.Security.WrapperSecurityCommunicationObject.OnOpen(TimeSpan timeout) at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) at System.ServiceModel.Channels.SecurityChannelFactory1.ClientSecurityChannel1.OnOpen(TimeSpan timeout) at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) at System.ServiceModel.Security.SecuritySessionSecurityTokenProvider.DoOperation(SecuritySessionOperation operation, EndpointAddress target, Uri via, SecurityToken currentToken, TimeSpan timeout) at System.ServiceModel.Security.SecuritySessionSecurityTokenProvider.GetTokenCore(TimeSpan timeout) at System.IdentityModel.Selectors.SecurityTokenProvider.GetToken(TimeSpan timeout) at System.ServiceModel.Security.SecuritySessionClientSettings1.ClientSecuritySessionChannel.OnOpen(TimeSpan 超时)在 System.ServiceModel.Channels.CommunicationObject.Open(时间跨度 超时)在 System.ServiceModel.Channels.ServiceChannel.OnOpen(TimeSpan 超时) 在 System.ServiceModel.Channels.CommunicationObject.Open(时间跨度 超时)在 System.ServiceModel.Channels.ServiceChannel.CallOpenOnce.System.ServiceModel.Channels.ServiceChannel.ICallOnce.Call(ServiceChannel 通道,TimeSpan 超时)在 System.ServiceModel.Channels.ServiceChannel.CallOnceManager.CallOnce(时间跨度 超时,CallOnceManager 级联)在 System.ServiceModel.Channels.ServiceChannel.EnsureOpened(时间跨度 超时)在 System.ServiceModel.Channels.ServiceChannel.Call(字符串动作, Boolean oneway, ProxyOperationRuntime 操作, Object[] ins, Object[] 出局,TimeSpan 超时)在 System.ServiceModel.Channels.ServiceChannel.Call(字符串动作, Boolean oneway, ProxyOperationRuntime 操作, Object[] ins, 对象 [] 出局)在 System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall,ProxyOperationRuntime 操作)在 System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage 消息)在 [0] 处重新抛出异常:在 System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg,IMessage retMsg)在 System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(消息数据& msgData,Int32 类型)在 > Proxy.FileTransferService.IFileTransferService.EstablishProxy(DownloadRequest 请求) 在 Proxy.FileTransferService.FileTransferServiceClient。 Proxy.FileTransferService.IFileTransferService.EstablishProxy(下载请求 请求)在 NormalFileTransferServiceClient.Download(Int32 packageId、IStreamWriter 下载器、Archiver 存档器)在 LoggingFileTransferServiceClient.Download(Int32 packageId, ISt

客户端正在抛出该异常。

IFileTransferService 的客户端代理配置为:

<binding name="WSHttpBinding_IFileTransferService" closeTimeout="00:01:00"
  openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
  bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
  maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Mtom"
  textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false">
  <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
    maxBytesPerRead="4096" maxNameTableCharCount="16384" />
  <reliableSession ordered="true" inactivityTimeout="00:10:00"
    enabled="false" />
  <security mode="Message">
    <transport clientCredentialType="Windows" proxyCredentialType="None"
      realm="" />
    <message clientCredentialType="UserName" negotiateServiceCredential="true"
      algorithmSuite="Default" establishSecurityContext="true" />
  </security>
</binding>

  <endpoint address="http://[hostname]/FileTransferService.svc/FileTransfer"
    binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IFileTransferService"
    contract="Proxy.FileTransferService.IFileTransferService"
    name="WSHttpBinding_IFileTransferService">
    <identity>
      <certificate encodedValue="a long string"/>
    </identity>
  </endpoint>

服务配置是

<service behaviorConfiguration="ServiceBehavior" 
    name="Services.FileTransferService">
        <endpoint name="WSHttpBinding_IFileTransferService" 
       binding="wsHttpBinding" 
       bindingConfiguration="MtomWSHttpBinding" 
       contract="Services.IFileTransferService" 
       address="/FileTransfer"/>
        <endpoint binding="basicHttpBinding" 
       bindingConfiguration="FileTransferServicesBinding" 
       contract="Services.IFileTransferService"/>
        <host>
          <baseAddresses>
            <add baseAddress="http://[hostname]/FileTransferService.svc"/>
          </baseAddresses>
        </host>
</service>

<binding name="wsHttpBinding" 
         maxReceivedMessageSize="2147483647" 
         receiveTimeout="5" 
         useDefaultWebProxy="false">
      <readerQuotas maxDepth="2147483647" 
             maxStringContentLength="2147483647" 
             maxArrayLength="2147483647" 
             maxBytesPerRead="2147483647" 
             maxNameTableCharCount="2147483647" />
  <security mode="Message">
    <message clientCredentialType="UserName" />
  </security>
</binding>

<basicHttpBinding>
    <binding name="FileTransferServicesBinding" 
           maxReceivedMessageSize="10067108864" 
           messageEncoding="Mtom" 
           transferMode="Streamed" 
           useDefaultWebProxy="false">
      <security mode="None">
        <message clientCredentialType="UserName" />
      </security>
    </binding>
  </basicHttpBinding>

注意:一些客户端正在使用 basicHttpBinding(如果我设置正确的话)。在客户端的后续版本中,可能尚未完全分发(这就是我必须支持 2 版本的原因),我将代理更改为使用 wsHttpBinding 端点。我想知道我得到的这个错误是否特定于 basicHttp,如果是这样,也许我没有正确设置这些配置。我假设收到此 403 错误的客户端正在使用 wsHttpBinding。

这是服务的代码:

public RemoteBinaryInfo EstablishProxy(DownloadRequest request)

    int packageId = request.PackageId;

    System.IO.MemoryStream stream = new System.IO.MemoryStream(packageRepository.GetPackageBinary(packageId));

    DisposeStreamWhenOperationIsComplete(stream, OperationContext.Current);

    RemoteBinaryInfo result = new RemoteBinaryInfo();
    result.Length = stream.Length;
    result.MemoryByteStream = stream;
    return result;



private static void DisposeStreamWhenOperationIsComplete(System.IO.MemoryStream stream, OperationContext clientContext)

    clientContext.OperationCompleted += new EventHandler(delegate(object sender, EventArgs args)
    
        if (stream != null)
            stream.Dispose();
    );

有谁知道摆脱这个异常是否在我的控制范围内?我可以对客户端或服务配置文件进行任何配置更改吗?

如果您需要我的更多信息,请告诉我。

【问题讨论】:

如果还没有做,你应该尝试公开一个简单的 hello world 方法来隔离问题。 【参考方案1】:

在我的例子中,这个错误来自我们组织的 HTTP 代理服务器。从以下位置找到它: MessageSecurityException.InnerException.Response.Headers:

Mime 版本:1.0 X-Squid-错误:ERR_ACCESS_DENIED 0 X-Cache:来自 的 MISS X-Cache-Lookup:无来自 代理连接:关闭 内容长度:2165 内容类型:text/html 日期:格林威治标准时间 2012 年 4 月 25 日星期三 10:55:39 服务器:squid/3.0.STABLE25 通过:1.0 (squid/3.0.STABLE25)

在我的情况下,它也发生在文件传输方法中,该方法在大小为 16384 的 byte 数组中传输文件块。将大小减小到 10000 时,错误已解决。这意味着代理服务器设置了某种大小限制。

在直接访问 Internet 的机器上,文件传输方法从未因此错误而失败,即使数组大小 > 16384。

由于只有您的一些客户端面临此问题,因此他们可能位于防火墙/代理服务器后面,而该服务器实际上阻止访问并返回此错误?

【讨论】:

这里也一样。忘记检查本地地址的绕过代理服务器【参考方案2】:

在我看来,收到 MessageSecurityException 的客户端没有在他们的请求中提供有效的用户名/密码。

查看下面的msdn主题http://msdn.microsoft.com/en-us/library/ms733131.aspx

【讨论】:

如果上述操作已经完成,收到错误的客户端之间是否存在连接?排除收到错误的客户端没有通过代理发送请求也很有用。如果这些都没有帮助,请在客户端和服务上启用消息跟踪:msdn.microsoft.com/en-us/library/ms730064.aspx 用户名和密码在解密后直接在代码中提供。客户端和这些服务之间没有人工交互。我生成的代理与应用程序一起分发并自动执行。 我已经有了这个 creds.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.PeerTrust;但这是否可以解决问题: creds.ServiceCertificate.Authentication.TrustedStoreLocation = StoreLocation.LocalMachine;我得到的错误并不是每个客户端请求都会发生,但可能是特定的客户端网络配置需要添加上面的代码。明确说明客户端中服务器证书的位置的目的是什么? 目前我在客户端代码中有 creds.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None,即使证书存储在远程主机上的 TrustPeople 存储中。【参考方案3】:

因此,您在 IIS 中配置了一个使用匿名身份验证的 Web 服务,但只有少数用户会收到 403 禁止错误。

根据我自己的经验,这通常是由访问 ACL 控制的系统资源(例如文件系统)时出现拒绝访问异常引起的。

如果该身份未添加到任何所需的访问控制列表拒绝访问异常将导致 IIS 响应 403 错误。

我通常将应用程序池标识添加到组,然后将该组添加到任何所需的资源。

如果您无法确定可能导致异常的资源,请尝试在安全事件日志中查找“审核失败”条目以获取线索。您可能需要配置本地安全策略来记录安全事件。

祝你好运

【讨论】:

以上是关于收到 403 禁止错误。客户端身份验证方案“匿名”禁止 HTTP 请求的主要内容,如果未能解决你的问题,请参考以下文章

客户端身份验证方案“匿名”禁止 HTTP 请求。 3

添加 WCF 服务引用时,HTTP 请求被客户端身份验证方案“匿名”错误禁止

IIS 托管具有 SSL 安全性的 WCF -“HTTP 请求被客户端身份验证方案‘匿名’禁止”错误

客户端身份验证方案“匿名”禁止 HTTP 请求

重现问题:客户端身份验证方案“匿名”禁止 http 请求

客户端身份验证方案“匿名”禁止 HTTP 请求