我之前就这个主题发表过帖子,但经过一年的其他事情,我再次设法陷入困境。我将尝试简要概述该场景以及当前使工作正常进行的尝试:
从 foo 提供的 Javascript 通过对 bar 上的 WCF 服务进行 RESTful ajax 调用(
GET
或 POST
,取决于操作)来工作,显然这些是跨域调用,因为它们不在同一主机上。Javascript 使用 jQuery (1.7.2) 框架来操作 DOM 并执行对 bar(
POSTS
的预期内容类型)的 ajax 调用。是 JSON
,以及来自 GETS
的响应预计为JSON
也是(应用程序/json)。Bar 使用
TransportCredentialOnly
配置了它的 WCF 服务作为安全模式和传输客户端凭据类型为 NTLM
,因此只有经过身份验证的用户才能联系服务。已使用 WCF 扩展将 CORS 支持添加到 bar 的 WCF 服务中:
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
}
});
事实证明你不能使用
"*"
当您使用 "withCredentials"
时接受的原点在 ajax 调用中:https://developer.mozilla.org/en/http_access_control
"Important note: when responding to a credentialed request, server must specify a domain, and cannot use wild carding."
目前在我们的开发实验室中,这并不重要,因为我们可以将请求硬编码到 IIS (foo) 服务器 URL。
现在的主要问题似乎是尝试
POST
请求( GET
使用上述配置工作)。当浏览器尝试 POST
进程,它首先发送一个 OPTIONS
请求允许的服务器的 header OPTIONS
为后续职位。这是我们希望看到我们在 CORS 支持 WCF 扩展中配置的 header 被传回的地方,但是我们还没有走那么远;在响应返回为“401 Unauthorized”之前,我相信这与请求 NTLM 的传输安全绑定(bind)配置有关,但我不确定。另外,我在这方面不是很有经验,但我没有看到太多关于
POST
的信息。使用 application/json
内容类型而不是 text/plain
执行跨域请求时。我知道人们可能会建议
JSONP
作为一个真正的解决方案,我并不反对不同的方法,确实我鼓励任何人提出最佳实践,因为它会帮助其他人稍后阅读这个问题。但是,请尝试在建议替代方案之前回答该问题。非常感谢任何做出贡献的人。
彼得斯基
:)
更新:
Chrome (20.x.x) 似乎没有遇到不协商 NTLM 来检索
OPTIONS
的问题。来自服务器的 header 响应,但 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 错误。
更新 2:
经过一番挖掘,似乎 IE8 的
XDomainRequest
不能用于发出必须协商 NTLM 的跨域请求,这基本上意味着由于 Web 浏览器的限制,无法使用 WCF 绑定(bind)的安全性。http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx
"No authentication or cookies will be sent with the request"
所以,我想我们现在已经采取了这个措施..看起来我们将不得不创建我们自己的自定义 token 身份验证并将其传递给 cookie 中的 WCF 服务,或者在 IE8 的情况下,
POST
它与 JSON。然后 WCF 服务必须处理解密数据并使用它而不是 ServiceSecurityContext.Current.WindowsIdentity
我们以前可以使用 NTLM 身份验证访问。
最佳答案
我知道您说过您希望问题本身得到解决,但您可以考虑使用“反向代理”。
我不知道您使用的是什么技术,但我们使用 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 服务器,瞧!
关于javascript - 使用 transportCredentialOnly 安全性对 RESTful WCF 服务的跨域 Ajax JSON POST 支持,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11330898/