一、基础概念
同源策略:
为安全考虑,浏览器会拒绝指向非同源网站的请求。同源指协议、域名、端口相同都相同。举例:
http://www.a.com,协议为http,域名www.a.com,端口默认80,则下面的同源与非同源举例:
http://www.a.com/...:同源;
https://www.a.com/...:不同源(协议不同);
http://service.a.com/...:不同源(域名不同);
http://www.b.com/...:不同源(域名不同);
http://www.a.com:8080/...:不同源(端口不同)。
跨域请求:
非同源的请求,需要跨域才能成功。跨域比较常用的有两种方法:CORS、JSONP,后者是一种非官方方法。
二、通过 Access-Control-Allow-Origin 实现跨域
实验思路:
1、环境配置:tomcat,jdk1.8;
2、实践目的:(1)、学会CORS 跨域访问的基础使用;(2)、探索能否多次跨域(即应用three请求应用one的资源,能否间接通过跨域请求应用two,而应用two再跨域请求应用one实现)
3、项目概况:三个web项目:WebAppOne(访问路径:http://appone.com:8080)、WebAppTwo(访问路径:http://apptwo.com:8080)、WebAppThree(访问路径:http://appthree.com:8080)
实践步骤:
1、项目WebAppOne:
ServletOfAppOne.java 关键代码:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setHeader("Access-Control-Allow-Origin", "*");
RequestDispatcher rd = request.getRequestDispatcher("indexOfAppOne.html");
rd.forward(request, response);
}
indexOfAppOne.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>应用One</title>
</head>
<body>
应用One 的首页
</body>
</html>
2、项目WebAppTwo
ServletOfAppTwo.java 关键代码:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//用于AppThree通过跨域请求此servlet 再次跨域请求AppOne 的服务
System.out.println("访问应用Two 成功");
response.setHeader("Access-Control-Allow-Origin", "*");
RequestDispatcher dispatcher = request.getRequestDispatcher("http://appone.com:8080/ServletOfAppOne");
dispatcher.forward(request,response);
}
indexOfAppTwo.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>应用Two</title>
</head>
<body>
<fieldset>
<legend>请求区</legend>
<button οnclick="requestAppOne()">跨域请求应用One</button>
</fieldset>
<fieldset>
<legend>请求结果</legend>
<div id="data"></div>
</fieldset>
<script type="text/javascript">
function ajax(url){
var xhr;
if(window.XMLHttpRequest){
xhr=new XMLHttpRequest();
}
else{
xhr=new ActiveXObject("Microsoft.XMLHTTP");
}
xhr.open("GET",url,true);
xhr.onreadystatechange=function(){
if(xhr.readyState==4&&xhr.status==200){
alert("请求成功");
var msg=xhr.responseText;
document.getElementById("data").innerHTML=msg;
}
}
xhr.send();
}
function requestAppOne(){
ajax("http://appone.com:8080/WebAppOne/ServletOfAppOne");
}
</script>
</body>
</html>
3、项目WebAppThree
indexOfAppThree.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>应用Three</title>
</head>
<body>
<fieldset>
<legend>请求区</legend>
<button οnclick="requestAppOne()">跨域请求应用One</button>
<button οnclick="requestAppOnePassByAppTwo()">通过跨域请求应用Two间接跨域请求应用One</button>
</fieldset>
<fieldset>
<legend>请求结果</legend>
<div id="data"></div>
</fieldset>
<script type="text/javascript">
function ajax(url){
var xhr;
if(window.XMLHttpRequest){
xhr=new XMLHttpRequest();
}
else{
xhr=new ActiveXObject("Microsoft.XMLHTTP");
}
xhr.open("GET",url,true);
xhr.onreadystatechange=function(){
if(xhr.readyState==4&&xhr.status==200){
alert("请求成功");
var msg=xhr.responseText;
document.getElementById("data").innerHTML=msg;
}
}
xhr.send();
}
function requestAppOne(){
ajax("http://appone.com:8080/WebAppOne/ServletOfAppOne");
}
function requestAppOnePassByAppTwo(){
ajax("http://apptwo.com:8080/WebAppOne/ServletOfAppTwo")
}
</script>
</body>
</html>
4、修改hosts 与tomcat 的service.xml 文件,配置项目域名
(1)、修改C:\Windows\System32\drivers\etc\hosts 文件,增加三条:
127.0.0.1 appone.com
127.0.0.1 apptwo.com
127.0.0.1 appthree.com
(2)、修改tomcat 的service.xml 文件,在<Host> 元素体内增加三条:
<Alias>appone.com</Alias>
<Alias>apptwo.com</Alias>
<Alias>appthree.com</Alias>
这样,便为本地tomcat 中项目配置了域名。
5、测试
(1)、浏览器地址栏输入:http://appone.com:8080/WebAppOne/ServletOfAppOne
结果:
(2)、http://apptwo.com:8080/WebAppTwo
结果:
(3)、http://appthree.com:8080/WebAppThree
结果:间接访问AppOne 时,服务器端servlet 中打印了语句,但提示404错误
结论:不能直接跨域访问,不能跨域后再跨域访问第三者。
6、修改WebAppOne 中servlet 允许跨域请求的源
将:
response.setHeader("Access-Control-Allow-Origin", "*");
替换为:
response.setHeader("Access-Control-Allow-Origin", "apptwo.com");
则,WebAppTwo 与WebAppThree都不能访问 WebAppOne 会提示错误:
事实上,经过若干次实践发现,判断能否跨域的工作过程如下:
1、只要服务器端设置了Access-Control-Allow-Origin 头,则所有对该服务的直接请求返回状态都是200,但不一定真正返回数据;
2、Access-Control-Allow-Origin 的值只能为* 或完整的 http://+域名+端口 的形式,如为 http://apptwo.com:8080 时,WebAppTwo 访问时才能真正拿到数据。
可使用数组等 与request 的referer 头等信息实现特定几个网站可访问此应用。
注意:
这种方式js 中ajax 请求时根本不需设置特殊请求头,实际上有的网友说的Origin 等请求头根本不存在,只需写完整路径就行。