使用transportCredentialOnly安全性对RESTful WCF服务的跨域Ajax JSON POST支持

时间:2012-07-04 14:19:29

标签: javascript wcf authentication rest cross-domain

我之前已经发过这个主题,但经过一年的其他事情,我已经设法再次进入泡菜。我将尝试简要概述一下场景以及目前使事情有效的尝试:

  • 在主机上托管HTML,JS等的IIS Web服务器: iis.mycompany.com (简称​​ foo
  • 通过主机上的Windows服务托管的WCF RESTful Web服务: wcf.mycompany.com (简称​​ bar

foo 提供的Javascript通过对栏上的WCF服务进行RESTful ajax调用(GETPOST,具体取决于操作)来工作,显然这些是跨域调用,因为它们不在同一主机上。

Javascript使用jQuery(1.7.2)框架来操作DOM并执行对 bar 的ajax调用,POSTS的预期内容类型为JSON,并且GETS的响应预计也是JSON(application / json)。

Bar 使用TransportCredentialOnly作为安全模式并且传输客户端凭据类型为NTLM配置了WCF服务,因此只有authed用户才能联系服务。

使用WCF扩展程序将 bar WCF服务添加到CORS支持中:

http://blogs.msdn.com/b/carlosfigueira/archive/2012/05/15/implementing-cors-support-in-wcf.aspx

我们添加了额外的标题,并根据众多互联网文章对帖子进行了修改:

property.Headers.Add("Access-Control-Allow-Headers", "Accept, Content-Type");
property.Headers.Add("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
property.Headers.Add("Access-Control-Max-Age", "172800");
property.Headers.Add("Access-Control-Allow-Origin", "http://iis.mycompany.com");
property.Headers.Add("Access-Control-Allow-Credentials", "true");
property.Headers.Add("Content-type", "application/json");

提供有关启用CORS的信息的站点建议Access-Control-Allow-Origin响应头应设置为"*"但是,在我们的情况下这是不可能的,因为我们使用以下设置进行jQuery ajax调用:

$.ajaxSetup({
  cache: "false",
  crossDomain: true,
  xhrFields: {
    withCredentials: true
  }
});

事实证明,当您在ajax调用中使用"*"时,您无法将"withCredentials"用于接受的来源:

https://developer.mozilla.org/en/http_access_control

  

"重要说明:在响应凭证请求时,服务器   必须指定一个域,并且不能使用野外梳理。"

目前在我们的开发实验室中,这并不重要,因为我们可以将请求硬编码到IIS(foo)服务器URL。

现在的主要问题似乎是尝试POST次请求(GET正在使用上述配置)。当浏览器尝试POST进程时,它首先向服务器发送OPTIONS标头,请求允许OPTIONS后续帖子。这是我们希望看到我们在CORS支持WCF扩展中配置的标头被传回的地方,但是我们还没有达到这个目的。在响应返回" 401 Unauthorized" 之前,我认为这与请求NTLM的传输安全绑定配置有关,但我不确定。

另外,我对此并不是很有经验,但在执行时我还没有看到有关POST使用application/json内容类型而不是text/plain的大量信息跨域请求。

我知道人们可能会建议JSONP作为一个真正的解决方案,我不反对不同的方法,实际上我鼓励任何人建议最佳实践,因为它可以帮助其他人稍后阅读这个问题。但是,请在建议替代方案之前尝试回答这个问题。

非常感谢任何有贡献的人。

peteski :)

更新

Chrome(20.x.x)似乎没有遇到不协商NTLM从服务器检索OPTIONS标头响应的问题,但Firefox(13.0.1)确实如此。

我们还注意到有人已经在Firefox论坛上发布了一个错误消息,我们已经在其中添加了信息:

http://bugzilla.mozilla.org/show_bug.cgi?id=751552

请投票支持在bugzilla网站上修复此错误!

使用以下代码,我们可以观看网络跟踪以查看Firefox失败并且Chrome工作正常:

var url = "http://myWebServiceServer/InstantMessagingService/chat/message/send";
var data = '{ "remoteUserUri" : "sip:foo.bar@mydomain.com", "message" : "This is my message" }';            
var request = new XMLHttpRequest();                     
request.open("POST", url, true);
request.withCredentials = true;
request.setRequestHeader("Content-Type", "application/json");                   
request.send(data);                     
console.log(request);

单独注意,IE8不支持XMLHttpRequest跨域调用,支持它自己的神奇XDomainRequest对象,所以我们有一些工作更改客户端代码以处理IE8与世界案例。 (感谢IE8)。

/ me穿过Mozilla修复Firefox bug的手指。

更新2:

经过一番挖掘后,似乎IE8的XDomainRequest不能用于制定必须协商NTLM的跨域请求,这基本上意味着我们的WCF绑定的安全性无法使用感谢网络浏览器的限制。

http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx

  

"请求和#34;

不会发送任何身份验证或Cookie

所以,我想我们现在已经采取了这个措施。看起来我们必须创建自己的自定义令牌身份验证并将其传递给WCF服务在cookie中,或在IE8的情况下,POST使用JSON。然后,WCF服务必须处理解密数据并使用它来代替我们之前使用NTLM身份验证访问的ServiceSecurityContext.Current.WindowsIdentity

1 个答案:

答案 0 :(得分:1)

我知道你说你宁愿解决问题本身,但你可以考虑使用“反向代理”。

我不知道您使用的是哪种技术,但我们使用Apache Web服务器并在需要身份验证的其他服务器上运行Java RESTful API。有一段时间,我们搞砸了JSONP和CORS,但并不满意。

最后,我们设置了一个Apache反向代理,它创造了奇迹。 Web浏览器认为它正在与自己的域进行通信并采取适当的行动。 RESTful API不知道它是通过代理使用的。因此,一切正常。而且Apache做了所有的魔术。

希望所有Web服务器都具有Apache的反向代理等功能。 以下是有关该功能的一些文档:http://httpd.apache.org/docs/2.2/mod/mod_proxy.html

我们所要做的就是确保安装了mod_proxy模块,然后将以下行添加到我们的Apache配置文件中:

ProxyPass /restapi http://restfulserver.com/restapi
ProxyPassReverse /restapi http://restfulserver.com/restapi

然后重新启动Web服务器,瞧!