因为浏览器的同源策略导致了跨域,就是浏览器在搞事情。
浏览器的同源策略,要同源说起。顾名思义,同源就是源头相同,即两个页面的协议、端口和域名都相同,任何一个不满足,都会导致跨域。
下表给出了相对http://www.baibai.com/say/one.html同源检测的示例:
URL | 结果 | 原因 |
---|---|---|
http://www.baibai.com/say/other.html | 成功 | 同一域名,同一文件夹 |
http://www.baibai.com/say/hi/another.html | 成功 | 同一域名,不同文件夹 |
https://www.baibai.com/say/oneByOne.html | 失败 | 不同协议 ( https和http ) |
http://www.baibai.com:81/say/two.html | 失败 | 不同域名 ( news和www ) |
http://news.baibai.com/say/three.html | 失败 | 不同域名 ( news和www ) |
如果是一般的ajax请求:
$.ajax({
url:'http://news.baibai.com/say/test/testjsonp',
type :'get',
dataType :'text',
success:function(data){
alert(data);
},
error:function(data){
alert(“error”);
}
});
那么在浏览器中会报错。
如果改用jsonp形式的ajax请求,并且通过get请求的方式传入参数,注意:跨域请求是只能是get请求不能使用post请求。
<!DOCTYPEhtml>
<html>
<head>
<metacharset="UTF-8">
<title>Inserttitle here</title>
<scripttype="text/javascript"src="./js/jquery.js"></script>
<scripttype="text/javascript">
$(document).ready(function(){
var newId = 1928273643';
$.ajax({
type :'get',
url:'http://news.baibai.com/say/test/testjsonp',
data : {
newId: newId,
},
cache:false,
jsonp:"callback",
jsonpCallback:"success",
dataType :'jsonp',
success:function(data){
alert(data);
},
error:function(data){
alert('error');
}
});
});
</script>
</head>
<body>
<input id=newId'value='546' name=’new'>
<divid='testdiv'></div>
</body>
</html>
jsonp 传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(默认为:callback)。
jsonpCallback自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名。
自从HTML5出现之后,极大地方便了日常的开发。其实浏览器并没有拦截请求,而是拦截了服务器端返回的响应。所以如果要支持跨域访问,需要浏览器和后台服务器程序同时支持,如果这两个条件不能同时满足,则还是不能支持跨域访问。
响应头有以下几种:
请求头有以下几种:
@Override
public void doFilter(ServletRequest request, ServletResponse response) throws IOException,ServletException {
HttpServletRequest req =(HttpServletRequest) request;
HttpServletResponse rep =(HttpServletResponse) response;
// 设置允许请求的域名,即白名单
String allowDomains = {"http://news.baibai.com/say/three.html "};
String originHeads = req.getHeader("Origin");
if(allowOrigins.contains(originHeads)){
rep.setHeader("Access-Control-Allow-Origin",originHeads);
}
}
有时候,在跨域访问的时候会存在访问方式是出了post,get类型的,比如options类型,这种会在有的代码中拦截,无法访问,需要在返回头中加如下字段:
response.setHeader("Access-Control-Allow-Methods","POST, GET, OPTIONS, DELETE");
有时候,访问的请求头首部出现其他类型, 那么Access-Control-Allow-Headers 响应首部预检请求,列出了将会在正式请求的 Access-Control-Expose-Headers 字段中出现的首部信息。如:
response.setHeader("Access-Control-Allow-Headers","x-requested-with,Origin,Accept");
有时候,会出现前端接口对接的时候,后台一直获取不到值。最后发现request里有值,session也有值,但是session的id却不一致。这就是因为跨域引起的,需要在fitter里加上以下代码:
response.setHeader("Access-Control-Allow-Credentials","true");
response.setHeader("XDomainRequestAllowed","1");
注意,当在后端Java代码中加入以上代码时,也需要在前端ajax中加入代码:
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
再次注意: 服务器端Access-Control-Allow-Credentials = true时,参数Access-Control-Allow-Origin的值不能为 '*'