1.cookie 跨域
在我们开发中可能会遇到不同域获取需要cookie转递问题,比如我们的sso 跨域问题。大概思路是这样的:
1)我们可以使用script标签无跨域问题进行处理,例如在我们访问b.com域时需要获取a.com中值,那么可以在我们a.com域jsp中添加下面脚本:
<script src="http://www.b.com/setCookie?name=token&value=123"></script>
在我们浏览器解析到该脚本时请求b域,在我们setCookie中获取参数并且设置其值,此时再访问我们b.com域时可以获取到该cookie值
缺点:有些浏览器会进行第三方cookie检测,只要是不同域就认为不安全(IE就是如此)
2)P3P协议
利用P3P协议设置避开浏览器检测问题,主要在我们servlet中设置浏览器header一些属性,关键代码:
response.addHeader("P3P", "CP=CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR");当浏览器解析到此处时认为安全的。
3)通过url传参
<iframe src="http://www.b.com/set_cookie?cname=token&cval=tttt"></iframe>
2.ajax 跨域请求
1)$.ajax("http://www.b.com/user_info").done(showResult);
在我们user_info中设置我们showResult回掉函数,写入页面
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// 要正确设置响应类型,避免IE出现下载
response.setContentType("application/javascript");
String userInfo = "{\"id\":1, \"name\":\"zhangsan\"}";
// 返回拼接的javascript语句字符串,语句本身执行一个调用函数的操作
// String ret = "showResult(" + userInfo + ");";
// 通过参数传递回调函数名,一定程度降低了前后端代码的耦合度
String callback = request.getParameter("callback");
String ret = callback + "(" + userInfo + ")";
response.getWriter().write(ret);
}
jsonp 支持:
// $.ajax({
// url: "http://www.b.com/user_info_2?callback=?",
// data: {id: 1},
// dataType: "jsonp"
// }).done(showResult);
});
2.设置header接受参数允许进行安全访问(普通请求)
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// 简单请求,直接设置Access-Control-Allow-Origin就可以了
response.addHeader("Access-Control-Allow-Origin", "*");
// 要正确设置响应类型,避免IE出现下载
response.setContentType("application/json");
response.getWriter().write("{\"id\":1, \"name\":\"zhangsan\"}");
}
3.非普通请求
$.ajax({
url: "http://www.b.com/user_info",
method: "POST",
beforeSend: function(xhr) {
console.log("before send");
xhr.setRequestHeader("reqid","abc")
}
}).done(showResult);
如果是这种请求,那么用上述doPost单独处理不可行,这时通过cros 处理方式进行,过程如下:
请求发起时,浏览器先判断当前是否是跨域的AJAX;
如果是,判断是否是普通类型请求(GET类型,无自定义头数据);
普通请求,直接发起GET到服务端,在响应头中寻找Access-Control-Allow-Origin,如果有且允许,处理响应结果;
不是普通请求(非GET类型,或有自定义头),先PreFlight(即发起一个method=OPTIONS)的请求,
要求返回Access-Control-Allow-Methods和Access-Control-Allow-Headers,内容体为空
PreFlight正确执行后,再发起GET请求,获得响应结果,并处理结果。
那么针对这种情况我们需要复写doOptions方法进行参数设置:
/**
* 非简单请求,如 POST类型请求,或请求中有其它自定义Header,会执行一次preflight操作,浏览器会发起一次OPTIONS类型请求<br>
* 要对OPTIONS请求给予正确应答
*/
@Override
protected void doOptions(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
System.out.println("OPTIONS");
response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Allow-Methods",
"GET, POST, OPTIONS, DELETE");
response.addHeader("Access-Control-Allow-Headers", "reqid, xxxx");
}