JQuery跨域基本身份验证调用

时间:2012-04-08 14:36:51

标签: jquery spring-security cross-domain basic-authentication cors

我已经使用Spring MVC构建了一个REST API后端,并使用Spring Security安装了基本的Auth。

我想从Javascript客户端对REST API进行跨域ajax调用。我不想使用JSONP,因为我不想限于GET调用。我使用CORS,我在服务器端放置了正确的标题。

假设我的REST API在域localhost:8087上,我的客户端在localhost:8086上,这是跨域调用。

在我的Javascript客户端中,我使用jQuery进行ajax调用:

<script>
        $.ajax ({
            url: "http://localhost:8087/SpringMVC/users/user1",
            beforeSend: function (xhr) { xhr.setRequestHeader ("Authorization", "Basic xxxxxxxxxxxx"); },
            success: function(val) { console.log(val); alert("success" + val); },
            error: function(val) { console.log(val); alert("error" + val); }
        });
</script>

我的问题是jQuery没有在HTTP请求中发送Authorization标头,我不知道为什么。我不明白因为我在beforeSend方法中这样做,所以它应该在HTTP请求中。结果:我有401错误。

当我尝试来自同一域localhost:8087的脚本时,不再是跨域,我没有问题。

怎么可能?

我的脚本只是一个测试。我不打算将我的用户名/密码放在客户端。但我想测试如何对基本的auth保护的REST API进行ajax调用。我想我必须在服务器端发送安全我的用户名/密码,REST API发送给我一个cookie,我不需要再传递用户名/密码,我的下一个ajax调用REST API。我是对的吗?

我已经使用Chrome Advanced REST客户端测试了我的REST API,它就是这样运作的。对于第一个请求,我需要传递授权标头。然后就不需要了。我的javascript网络客户端是否也可以这样工作?我打算将Node.JS与Backbone一起使用来构建它。

非常感谢。

EDIT2 :似乎真的是一个CORS浏览器问题。我在服务器端添加了标题Access-Control-Allow-Methods for OPTIONS方法,它适用于Chrome。我可以访问JSON响应,不再出错。但是我仍然需要为下一个请求使用授权标头。如何告诉jQuery使用发送的cookie?

当我尝试使用Firefox 11时,我无法访问json响应并且出现错误:

"NetworkError: 401 Non-Autorisé - http://localhost:8087/SpringMVC/users/user1"

2 个答案:

答案 0 :(得分:8)

显然,Chrome和Firefox对待跨域请求的方式略有不同。 在执行跨域请求之前,他们使用HTTP OPTIONS方法执行所谓的“预检”请求。 Chrome和Firefox之间的区别在于,Chrome还会使用凭据发送授权标头,而Firefox则不会。

然后,它仍然是Spring Security配置问题。我的url / users / *对所有HTTP方法都是安全的,包括OPTIONS。对于Firefox,由于未发送Authorization标头,我的请求未获得授权。如果我仅将我的安全url / users / *限制为GET方法,那么它完全适用于Firefox。所以我不得不在我的Spring安全配置中添加它:

<intercept-url pattern="/users/*" access="isAuthenticated()" method="GET"/>

之后,我可以选择:我可以在intercept-url中添加其他方法来保护,OPTIONS除外,或者我可以在我的Spring MVC控制器中限制对GET的HTTP方法调用,这甚至会处理我的OPTIONS调用根据Javadoc。我选择了第二种解决方案。但如果有人找到迫使Firefox发送Chrome等凭据的解决方案,那就太棒了,我会选择这个。

答案 1 :(得分:2)

rico 提供的Spring Security配置方案的另一个选项是:

<http ... use-expressions="true">
    <intercept-url pattern="/users/*" access="permitAll" method="OPTIONS"/>
    <intercept-url pattern="/users/*" access="isAuthenticated()"/>
    ...
</http>

HTTP OPTIONS请求将始终通过身份验证,而任何其他HTTP方法都不会。

请注意use-expressions元素中<http> XML属性设置为 true 。然后,Spring Security会期望access元素的<intercept-url>属性包含 Spring EL表达式,例如 permitAll isAuthenticated()< /强>