加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

asp.net – 未在生产服务器中的WCF调用上传递凭据

发布时间:2020-12-16 03:20:22 所属栏目:asp.Net 来源:网络整理
导读:场景 我们有一个Web应用程序,使用以下代码调用Web服务(在IIS中托管在同一台机器上): – using (HttpContext.Current.Request.LogonUserIdentity.Impersonate()){ var client = new Services.ReportFormatter(endpointName); // endpoint name is configured
场景

我们有一个Web应用程序,使用以下代码调用Web服务(在IIS中托管在同一台机器上): –

using (HttpContext.Current.Request.LogonUserIdentity.Impersonate())
{
    var client = new Services.ReportFormatter(endpointName);  // endpoint name is configured in config
                                                       // Services.ReportFormatter is the generated client code using svcutil
    var response = client.DoWork();
}

代码的意图是使用Web应用程序用户的凭据执行WCF调用(我希望这显然是显而易见的!)并且代码就像Dev和QA机器上的魅力一样.不用说,它在生产中失败了!

问题

生成的.Net异常是

HTTP请求未经授权使用客户端身份验证方案“Negotiate”.从服务器收到的身份验证标头是“Negotiate,NTLM,Basic realm =”Services“’. InnerException:远程服务器返回错误:(401)未经授权.

有趣的是,IIS日志表明没有在WCF请求上传递用户凭据

Fields: 
cs-method cs-uri-stem cs-uri-query              s-port cs-username c-ip sc-status sc-substatus sc-win32-status 
GET       /MyWebApp/MyPage.aspx                   - 443 chrisf x.x.x.x
POST      /MyServicesApp/ReportFormatter.svc/ntlm - 80  -            x.x.x.x 401 2 2148074254
POST      /MyServicesApp/ReportFormatter.svc/ntlm - 80  -            x.x.x.x 401 1 0
POST      /MyServicesApp/ReportFormatter.svc/ntlm - 80  -            x.x.x.x 401 1 2148074252

请注意,对Web应用程序的请求记录了我的用户名 – 但是对服务的请求没有.将这些日志与我的开发机器中的日志进行比较,我在两个请求中都看到了我的名字 – 所以我认为这是失败的原因.

这是WCF配置 – 尽管它在Dev QA中工作的事实让我怀疑这不是错误的.任何想法/帮助将不胜感激.

Web应用程序(即WCF客户端)配置.

<bindings>
  <basicHttpBinding>

    <binding name="ReportFormatter" closeTimeout="00:01:00" openTimeout="00:01:00"
        receiveTimeout="00:10:00" sendTimeout="00:05:00" allowCookies="false"
        bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
        maxBufferSize="6553600" maxBufferPoolSize="524288" maxReceivedMessageSize="6553600"
        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="Windows" />
        <message clientCredentialType="UserName" />
      </security>
    </binding>
  </basicHttpBinding>
</bindings>

<client>
  <endpoint binding="basicHttpBinding" bindingConfiguration="ReportFormatter" contract="Services.ReportFormatter"
    name="ReportFormatter_Endpoint" address="http://localhost/MyServicesApp/ReportFormatter.svc/ntlm"/>
</client>

Web服务应用程序的配置文件包含此内容

<bindings>
        <basicHttpBinding>
            <binding name="BasicHttpWindowsBindingWinCred" maxReceivedMessageSize="20000000">
                <readerQuotas maxStringContentLength="20000000" maxArrayLength="1000000" maxBytesPerRead="20000000" />
                <security mode="TransportCredentialOnly">
                    <!-- clientCredentialType Windows requires IIS to be configured to support Windows authentication-->
                    <transport clientCredentialType="Windows" />
                    <message clientCredentialType="UserName" />
                </security>
            </binding>
        </basicHttpBinding>
    </bindings>## Heading ##
    <services>
      <service behaviorConfiguration="IIS.Service1Behavior" name="Services.FormatReportImpl">
          <endpoint address="ntlm" binding="basicHttpBinding" bindingConfiguration="BasicHttpWindowsBindingWinCred" name="FormatReportBindingWindowsAuthentication" contract="Services.ReportFormatter" bindingNamespace="http://www.donkey.com/Reporting" />
      </service>
    </services>

OS详细信息

制作:Win 2003 32bit SP2(IIS 6.0)

QA:Win 2003 32位SP2(IIS 6.0)

开发:各种各样!我自己的系统是Win7 64(IIS 7.5) – 我们在Vista上也有开发人员.

问题的原因和解决方案

像往常一样,魔鬼在细节.为什么哦为什么总是在细节!如果他们帮助其他有类似问题的人,则包括血腥细节.

原因

为了使问题尽可能简单,我没有提到Web应用程序和Web服务未托管在默认的IIS网站中.相反,它们托管在一个单独的网站上(原因是我们在同一台服务器上托管了同一个应用程序的几个应用程序版本),我们使用主机头信息来识别网站.

因此,只能通过“app.companyName.com”之类的URL访问生产站点(和Web服务).因此当我说客户端web.config有地址=“http://localhost/MyServicesApp/ReportFormatter.svc/ntlm”时,我撒了谎

它实际上有

地址= “http://app.companyName.com/MyServicesApp/ReportFormatter.svc/ntlm”

我觉得现在有点愚蠢,因为我知道我们无法跨越机器边界传递NTLM身份验证令牌 – 就WCF客户端而言,“app.companyName.com”是一个远程机器;它不知道DNS映射回到同一台机器 – 它可能没有想法(继续阅读).

借口

为了原谅我的愚蠢,这是一个借口:我在问题中撒谎的原因是我已经检查过上述类型的设置在QA服务器上有效.我检查了以下工作在客户端的WCF配置地址工作在QA机器上.

地址= “HTTP://qaServerName.domainName.local/MyServicesApp/ReportFormatter.svc/ntlm”

我在逻辑上认为,该地址必须转到域DNS才能解析,因此逻辑上会经历与“app.companyName.com”相同的处理.我甚至设置了“dnsAliasForTheQAServer”的DNS别名(在我们的本地域上),然后测试了以下工作

地址= “HTTP://dnsAliasForTheQAServer.domainName.local/MyServicesApp/ReportFormatter.svc/ntlm”

它确实做到了!现在你必须承认,如果机器认为它被称为“qaServerName”,那么你会认为“dnsAliasForTheQAServer.domainName.local”将被视为远程地址.所以我推断这可能不是导致生产服务器失败的问题.

只有当绝望导致我们实际创建一个新的DNS记录(“qaServerNameDnsRecord2”),我们设法重现QA机器上的错误!因此,我得出结论,在WCF客户端和/或DNS上进行了一些非常聪明的名称解析,解析了以下主机名

>“qaServerName”
>“qaServerName.domainName.local”
>“dnsAliasForTheQAServer.domainName.local”

到qaServerName – 因此逻辑上是“Localhost”(因为客户端和服务器都在同一台机器上)
但是当主机名称时,名称解析并不聪明

>“qaServerNameDnsRecord2”
>“qaServerNameDnsRecord2.domainName.local”

我相信如果我知道关于DNS的事情或者Windows如何解析名称,那么这不会是一个惊喜.但我了解到,将来我不会那么快

解决方案

知道问题是地址解析为一个看起来像是远程的地址,解决方案很简单 – 只需使地址看起来是本地的(如果Web服务托管在默认的超级网站中) easy – 只需将address =“http:// localhost / …”作为端点地址!).

我尝试的第一件事是编辑QA服务器上的hosts文件,并添加一个将’app.companyName.com’映射到127.0.0.1的条目,但这不起作用.

所以我做的下一个(相当不优雅)的事情是为主机标题值为127.0.0.1的网站添加额外的标识,然后将配置更改为读取地址=“http://127.0.0.1 / …” (我想我可以使用localhost而不是127.0.0.1).这就把一切都排好了.

解决方法

我想在生产中WCF和webserver在不同的机器上运行,在DEV和QA中它们不是?

您需要通过Kerberos身份验证委派用户身份才能用于模拟WCF.原因:WCF不知道用户凭据,因此无法正确模拟.在Kerberos方案中,将使用身份验证令牌而不是真实凭据.

如果您需要一个起点来进入Kerberos主题,请谷歌搜索“Kerberos IIS delegation 2003 Windows身份验证”或类似内容.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读