将NTLM凭据传递给远程Web服务

时间:2013-09-09 23:28:13

标签: c# javascript jquery iis cross-domain

我想将NTLM凭据传递给远程Web服务。

我从rm1.domain.com加载我的页面,在其Javascript中,rm2.domain.com上的网络服务被调用。

我希望调用的Web服务能够读取执行调用的用户的NTLM凭据,但我遇到了一些问题。

情景A(无效)

如果我的配置文件中包含以下内容:

 <webHttpEndpoint>
        <standardEndpoint name="" 
         automaticFormatSelectionEnabled="true" 
         crossDomainScriptAccessEnabled="true">
          <security>
            <transport clientCredentialType="Ntlm"></transport>
          </security>
       </standardEndpoint>
 </webHttpEndpoint>

并且只在IIS中启用了Windows身份验证,我得到了预期的结果:

enter image description here

场景B(无效)

我的配置文件中有以下内容

<webHttpEndpoint>
  <standardEndpoint name="" automaticFormatSelectionEnabled="true">
      <security>
        <transport clientCredentialType="Ntlm"></transport>
      </security>
  </standardEndpoint>
</webHttpEndpoint>

以及我的JavaScript中的以下内容:

jQuery.ajax({
    url: "http://rm2.domain.com/getInfo?name=bobsyouruncle,
    dataType: "json",
    async: false,
    success: function(data) {
        console.log('woot');
    },
    error: function(ex) {
        console.log(ex);
    }
});

并且只在IIS中启用了Windows身份验证,浏览器会抛出:

如果我将我的JavaScript更改为JSONP,那么我也什么也得不到,但是当我从web.config中删除 crossDomainScriptAccessEnabled =“true”时,这并不意外。但正如您将在方案C中看到的那样,在启用了身份验证方案的情况下,您无法使用 crossDomainScriptAccessEnabled =“true”

场景C(不会传递凭据)

如果mr2的web服务的web.config与方案B类似,则启用IIS身份验证匿名(并禁用Windows身份验证),并且jQuery的请求为JSONp,然后服务返回数据,但不传递身份验证信息。

底线(TL; DR) 有没有办法让我的Web服务作为IIS匿名,在其web.config中使用跨域标记,从浏览器传递域(NTLM)凭据并在我的Web服务的代码隐藏中解析它们。

文档和绝对数量的选项令人难以招架。

3 个答案:

答案 0 :(得分:0)

如果你看一下像fiddler这样的检查员的流量,客户端和服务器之间是否正确握手?启用Windows身份验证后,服务器将收到一个响应,其中包含一个标头,指示客户端(浏览器)应发送服务器接受的NTLM令牌并继续进行实际响应。

如果您在同一个域上托管Web服务,您可能能够隔离两个问题,以解决凭据问题,一旦工作,您可以专注于CORS问题。

要部分回答您的问题,匿名身份验证的网站将不会请求NTLM(或Kerberos)令牌

答案 1 :(得分:0)

看看这个,对使用NTLM和模仿有一些有趣的观点。

The HTTP request is unauthorized with client authentication scheme 'Ntlm'

我知道您的问题不是特定于WCF的,但有些问题与您的方案无关。

最后评论&#34; authenticationScheme和proxyAuthenticationScheme to&#34; Ntlm&#34;对你来说很有意思。

答案 2 :(得分:0)

抱歉,我不确切知道您尝试传递的数据类型,但如果唯一的问题是跨域ajax调用,只需在目标域上放置一个新的HTML文件即可将代表调用页面执行ajax调用。

如果要进行ajax调用,请在指向iframe位置的文档中插入新的iframe,并将数据传递给查询字符串。

function sendData(data){     var datastring = JSON.stringify(data);     var el = document.createElement(&#34; iframe&#34;);     el.src =&#34; // rm2.domain.com/iframe.html?data="+encodeURIComponent(datastring);     如果(el.style){el.style.display =&#34;无&#34 ;;}     document.body.appendChild(EL); }

iframe接收数据,进行ajax调用,然后通过URL片段将值发送回原始页面:

<!DOCTYPE html>
<html lang="en-US">

<head>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script type="text/javascript">
if(document.referrer=="rm1.domain.com" ){
    var querystring=window.location.search.split("&");
    var datastring="";
    var data;
    for(var q=0;q<querystring.length;q++){
        if(querystring[q].split("=")[0]=="data"){datastring=querystring[q].slice("data".length+1);}
    }
    if(datastring){data=JSON.parse(datastring);}

    jQuery.ajax({
        url: "/getInfo?name=bobsyouruncle",
        dataType: "json",
        data:data,
        async: false,
        success: function(data) {
            top.location="#data="+JSON.stringify(data);
        },
        error: function(ex) {
            top.location="#error="+JSON.stringify(ex);
        }
    });
}
</script>
</head>
</html>

原始页面可以定期检查数据(例如,在添加iframe时使用setInterval设置)。如果需要发送多个请求,也可以传递要清除的间隔的标识符。如果您可以将用户群限制为符合HTML5标准的浏览器,那么您可以减少&#34; hackish&#34;在window.postMessage方法中来回传递数据的方法。所有这些额外的细节都可以在这里找到:http://softwareas.com/cross-domain-communication-with-iframes