Cors技术,涉及服务器和浏览器。经过测试,只有服务器授权的站点才能资源共享,至少需要Access-Control-Allow-Origin授权,
授权为*时,withCredentials只能是false,Ajax每次都相当于独立的请求,与前后请求无关。
Access-Control-Allow-Origin授权指定站点,withCredentials设置为true时,Ajax几次请求相当于一个会话里。
下面例子模拟了一个会话过程。
服务端:
跨域,可以写一个Filter,放到Filter chain最前面。
if (crossDomain)
{
String origin = req.getHeader("Origin");
//if (servletPath.contains("*.jsp") || servletPath.contains("/login") || servletPath.contains("/login.jsp") || servletPath.contains("/controller"))
{
res.addHeader("Access-Control-Allow-Origin", origin); //这里是设定的允许的域
res.addHeader("Access-Control-Allow-Headers", "X-CSRF-TOKEN");//这里主要是CSRF验证需要
res.addHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH");
res.addHeader("Access-Control-Allow-Credentials", "true");
}
String method = req.getMethod();
if (method.equals("OPTIONS"))
{
//默认OPTIONS的反应是返回302,Ajax对于302反应大家可以自己跟踪。
res.setStatus(200);
return;
}
}
js前端:不多解释,直接上代码。
(function($) {
"use strict";
var Business = Business || {};
var RC = Business.RC = function () { };
RC.prototype.login = function() {
var d = $.Deferred();
var data = {
username:"sam",
password:"xxx"
};
var csrf_name = "";
var csrf_value = "";
var host = "http://192.168.1.102:8080";
function form()
{
$.ajax({
type: "GET",
crossDomain: true,
url: host + "/ShoppingMallWeb/login.jsp",
dataType: "text",
xhrFields: {
withCredentials: true // 为true时,Access-Control-Allow-Origin不能是*
},
complete: function (xhr, s) {
if (xhr.status == 200)
{
var result = xhr.responseText;
var ps = "";
var m = result.match(ps);
data[m[1]] = m[2];
csrf_name = m[1];
csrf_value = m[2];
d.resolve(result);
}
else
{
d.reject(xhr.responseText);
}
}
});
return d.promise();
}
function login() {
var d = $.Deferred();
$.ajax({
type: "POST",
crossDomain: true,
url: host + "/ShoppingMallWeb/controller/smw/login",
//url:host + "/ShoppingMallWeb/login",
beforeSend: function (request) {
request.setRequestHeader("X-CSRF-TOKEN", csrf_value);
request.setRequestHeader("Accept", "text/plain, **; q=0.01");
request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
},
dataType: "text",
xhrFields: {
withCredentials: true
},
data: data,
complete: function (xhr, s) {
if (xhr.status == 200) {
d.resolve(xhr.responseText);
}
else {
d.reject(xhr.responseText);
}
}
});
return d.promise();
}
function get() {
var d = $.Deferred();
$.ajax({
type: "GET",
crossDomain: true,
url: host + "/ShoppingMallWeb/controller/smw/get/sam",
dataType: "text",
xhrFields: {
withCredentials: true
},
complete: function (xhr, s) {
if (xhr.status == 200) {
alert(xhr.responseText);
d.resolve(xhr.responseText);
}
else {
d.reject(xhr.responseText);
}
}
});
return d.promise();
}
function post() {
var d = $.Deferred();
$.ajax({
type: "POST",
crossDomain: true,
url: host + "/ShoppingMallWeb/controller/smw/post/sam",
dataType: "text",
xhrFields: {
withCredentials: true
},
complete: function (xhr, s) {
if (xhr.status == 200) {
alert(xhr.responseText);
d.resolve(xhr.responseText);
}
else {
d.reject(xhr.responseText);
}
}
});
return d.promise();
}
form().then(login).then(get).then(post).then(logout);
};
$.rc = new RC();
})(jQuery);
上面代码,如果是从***.**发起的话,都通过了,包括IE(edge)、Firefox、Chrome,如果是从file://***发起的话,IE(edge)是不行的,Chrome和firefox是可以的,采用cordova技术的Android上的webview也不行。