使用Spring安全性的java跨源资源共享
我试图让CORS与Spring Security配合得很好,但它没有遵守。我做了this article中描述的更改,并且在applicationContext-security.xml
中更改这一行已经获得了我的应用程序的POST和GET请求(临时公开控制器方法,以便我可以测试CORS):
- 之前:
<intercept-url pattern="/**" access="isAuthenticated()" />
- 之后:
<intercept-url pattern="/**" access="permitAll" />
不幸的是,以下允许通过AJAX进行Spring安全登录的URL没有响应:http://localhost:8080/mutopia-server/resources/j_spring_security_check
。我正在从http://localhost:80
向http://localhost:8080
发出AJAX请求
铬
当尝试访问j_spring_security_check
时,我在Chrome中获得(pending)
选项飞行前请求和AJAX调用返回,HTTP状态代码为0,消息为“error”
在Firefox中
预飞行成功,HTTP状态代码为302,之后我仍然直接收到AJAX请求的错误回调,HTTP状态为0,消息为“error”
AJAX请求代码
function get(url, json) {
var args = {
type: 'GET',
url: url,
// async: false,
// crossDomain: true,
xhrFields: {
withCredentials: false
},
success: function(response) {
console.debug(url, response);
},
error: function(xhr) {
console.error(url, xhr.status, xhr.statusText);
}
};
if (json) {
args.contentType = 'application/json'
}
$.ajax(args);
}
function post(url, json, data, dataEncode) {
var args = {
type: 'POST',
url: url,
// async: false,
crossDomain: true,
xhrFields: {
withCredentials: false
},
beforeSend: function(xhr){
// This is always added by default
// Ignoring this prevents preflight - but expects browser to follow 302 location change
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xhr.setRequestHeader("X-Ajax-call", "true");
},
success: function(data, textStatus, xhr) {
// var location = xhr.getResponseHeader('Location');
console.error('success', url, xhr.getAllResponseHeaders());
},
error: function(xhr) {
console.error(url, xhr.status, xhr.statusText);
console.error('fail', url, xhr.getAllResponseHeaders());
}
}
if (json) {
args.contentType = 'application/json'
}
if (typeof data != 'undefined') {
// Send JSON raw in the body
args.data = dataEncode ? JSON.stringify(data) : data;
}
console.debug('args', args);
$.ajax(args);
}
var loginJSON = {"j_username": "username", "j_password": "password"};
// Fails
post('http://localhost:8080/mutopia-server/resources/j_spring_security_check', false, loginJSON, false);
// Works
post('http://localhost/mutopia-server/resources/j_spring_security_check', false, loginJSON, false);
// Works
get('http://localhost:8080/mutopia-server/landuses?projectId=6', true);
// Works
post('http://localhost:8080/mutopia-server/params', true, {
"name": "testing",
"local": false,
"generated": false,
"project": 6
}, true);
请注意-除了Spring安全登录,我可以通过CORS发布到我应用程序中的任何其他URL。我已经阅读了很多文章,因此对这个奇怪问题的任何见解都将不胜感激
# 1 楼答案
大多数情况下,选项请求不包含用于验证spring安全性的cookie
为了解决这一问题,可以修改spring security的配置,以允许选项请求而无需身份验证
我做了很多研究,得到了两种解决方案:
1.使用Java配置和spring安全配置
二,。使用XML(注意。不能写“POST,GET”):
最后是the source for the solution...:)
# 2 楼答案
这是我的代码,对我来说非常好,非常完美:我花了两天时间研究它,了解spring安全性,所以我希望你接受它作为答案,哈哈
那么您还需要设置要调用的过滤器:
您需要一个bean来创建自定义过滤器:
# 3 楼答案
对我来说,问题是
OPTIONS
飞行前检查未能通过身份验证,因为在该调用中没有传递凭据这对我很有用:
相关部分包括:
这解决了飞行前的问题。这里发生的事情是,当你收到一个呼叫,身份验证失败时,你检查它是否是一个
OPTIONS
呼叫,如果是,就让它通过,让它做它想做的一切。这实际上禁用了所有浏览器端的飞行前检查,但正常的跨域策略仍然适用当您使用最新版本的Spring时,可以使用下面的代码全局地允许跨源请求(适用于所有控制器):
请注意,这样硬编码很少是个好主意。在我工作过的几家公司中,允许的源代码可以通过管理门户进行配置,因此在开发环境中,您可以添加所需的所有源代码
# 4 楼答案
就我而言,答案是肯定的。getWriter()。flush()不起作用
更改代码如下,它开始工作
# 5 楼答案
我可以通过扩展UsernamePasswordAuthenticationFilter来做到这一点。。。我的代码是Groovy,希望没问题:
上面重要的几点:
您需要在Spring配置中声明这个bean。有很多文章展示了如何做到这一点,所以我不会在这里复制
在我自己的实现中,我使用了一个源域名白名单,因为我只允许内部开发者访问CORS。以上是我正在做的事情的简化版本,可能需要调整,但这应该给你一个大致的想法
# 6 楼答案
自Spring Security 4.1以来,这是使Spring Security支持CORS的正确方法(Spring Boot 1.4/1.5中也需要):
以及:
不要执行以下任何操作,这是解决问题的错误方法:
http.authorizeRequests().antMatchers(HttpMethod.OPTIONS, "/**").permitAll();
web.ignoring().antMatchers(HttpMethod.OPTIONS);
参考:http://docs.spring.io/spring-security/site/docs/4.2.x/reference/html/cors.html