10

我已经构建了Spring MVC的REST API后端,并使用Spring Security基本身份验证进行了安全保护。JQuery跨域基本认证调用

我想从JavaScript客户端跨域Ajax调用REST API。我不想使用JSONP,因为我不想限制GET调用。我使用CORS,并将正确的标题放在服务器端。

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

在我的JavaScript客户端,我做的AJAX调用使用jQuery:

<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请求的授权头,我不知道为什么。我不明白,因为我在beforeSend方法中这样做,所以它应该在HTTP请求中。结果:我有一个401错误。

当我尝试从相同的域本地主机:8087,这是不是跨域的脚本了,我没有问题。

这怎么可能?

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

我已经使用Chrome高级REST客户端测试了我的REST API,它的工作方式与此类似。对于我需要传递授权标头的第一个请求。然后它不是必需的。它应该像我的JavaScript网络客户端那样工作吗?我打算使用Node.JS和Backbone来构建它。

非常感谢。

EDIT2:似乎真的是一个CORS浏览器问题。我在服务器端为OPTIONS方法添加了头部访问控制 - 允许 - 方法,它可以在Chrome上运行。我有权访问JSON响应,而不再有错误。但我仍然需要为下一个请求使用授权标头。如何告诉jQuery使用发送的cookie?

当我与Firefox 11尝试,我必须JSON响应进不去,我有错误:

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

你是base64编码你的用户名/密码? – 2012-04-08 14:59:21

+0

是的,我把它xxxxxxxx而不是真正的用户名:密码。 – rico 2012-04-08 15:15:25

回答

8

显然,Chrome和Firefox治疗跨域请求有点不同。 在进行跨域请求之前,他们使用HTTP OPTIONS方法执行所谓的“预检”请求。 Chrome和Firefox之间的区别在于,Chrome也会将Authorization标头与凭据一起发送,而Firefox则不会。

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

<intercept-url pattern="https://stackoverflow.com/users/*" access="isAuthenticated()" method="GET"/> 

之后,我有选择,我可以添加其他方法固定在拦截的URL,除了选项,或者我可以限制HTTP方法在我的Spring MVC控制器中调用GET,它甚至可以根据Javadoc处理我的OPTIONS调用。我选择了第二种解决方案。但是,如果有人找到解决方案来强制Firefox发送像Chrome那样的凭据,那将会很棒,我会选择这个。

2

波多黎各呈现将是春季安全配置方案的另一种选择:

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

HTTP OPTIONS请求都将通过认证和任何其他HTTP方法不会。

请注意use-expressions XML属性设置为true in <http> element。那么Spring Security将期望<intercept-url>元素的access属性包含春EL表达式,像permitAllisAuthenticated()