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

pet*_*ski 8 javascript authentication rest wcf 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调用,期望的内容类型为POSTSis JSON,并且响应来自GETS预期JSON(application/json).

Bar使用TransportCredentialOnly作为安全模式配置的WCF服务和传输客户端凭证类型NTLM,因此只有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");
Run Code Online (Sandbox Code Playgroud)

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

$.ajaxSetup({
  cache: "false",
  crossDomain: true,
  xhrFields: {
    withCredentials: true
  }
});
Run Code Online (Sandbox Code Playgroud)

事实证明,"*"当您"withCredentials"在ajax调用中使用时,您无法使用已接受的原点:

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.xx)似乎没有遇到不协商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);
Run Code Online (Sandbox Code Playgroud)

另外,IE8不支持XMLHttpRequest跨域调用,支持它自己的魔法XDomainRequest对象,因此我们在更改客户端代码以处理IE8与世界案例方面有一些工作要做.(谢谢IE8).

/我穿过Mozilla修复Firefox bug的手指.

更新2:

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

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

"不会随请求发送身份验证或Cookie"

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

Nos*_*.io 1

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

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

最后,我们设置了一个 Apache 反向代理,它创造了奇迹。网络浏览器认为它正在与自己的域进行通信并采取适当的行动。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
Run Code Online (Sandbox Code Playgroud)

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