初学,表述不规范之处还望不吝赐教。
1、基本思路
在 Windows 主机与 Linux 虚拟机上同时启动 tomcat 服务器,分别模拟跨域的客户端和服务器端。当客户端(Windows)通过页面 ajax 请求服务器端(Linux)的数据时,如果请求头的 Origin 与响应头的 Access-Control-Allow-Origin 匹配成功,则传回 JSON 格式的请求数据;如果允许多个域名访问,则让 Origin 与一个域名数组(白名单)进行逐一比较,匹配成功则显示相应数据。
2、域名准备
(1)客户端域名:http://www.corsdemo.com:8080(即 127.0.0.1)
(2)服务器域名:http://192.168.92.88:8080
(3)实测任务描述:让客户端用两种域名(http://www.corsdemo.com:8080/ 和 http://localhost:8080/)实现 CORS 跨域访问服务器,并显示所需数据结果。
3、客户端准备
Windows:%CATALINA_HOME%\webapps\ROOT\DemoCORS.html
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>CORS Demo</title>
<script
src="http://code.jquery.com/jquery-3.2.1.min.js"
integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
crossorigin="anonymous"></script>
<script>
$(function(){
$("#msg").click(function(){
$.post("http://192.168.92.88:8080/DemoCORS/CorsServlet",function(data){
alert(data);
$("#msg").html("My name is " + data.name + ", at age of " + data.age + "," +
(data.isEngineer ? " an engineer" : "") + " from " + data.company);
},"json");
});
});
</script>
</head>
<body>
<h1>CORS Demo</h1>
<h2 id="msg">单击实现 CORS 跨域访问</h2>
</body>
4、服务器端准备
(1)Servlet:(Linux)%CATALINA_HOME%/DemoCORS/WEB-INF/classes/action/CorsServlet.java
@WebServlet("/CorsServlet")
public class CorsServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public CorsServlet() { super(); }
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String[] whiteList = {"http://www.corsdemo.com:8080", "http://localhost:8080"};
String myOrigin = request.getHeader("origin");
boolean isValid = false;
for( String ip : whiteList ) {
if( myOrigin != null && myOrigin.equals(ip) ){
isValid = true;
break;
}
}
response.setHeader("Access-Control-Allow-Origin", isValid ? myOrigin : "null");
User user = new User("Andy", 28, "Google", true);
String data = new Gson().toJson(user);
response.setCharacterEncoding("UTF-8");
response.getWriter().print(data);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
(2)请求数据:(Linux)%CATALINA_HOME%/DemoCORS/WEB-INF/classes/entity/User.java
public class User {
private String name;
private int age;
private String company;
private boolean isEngineer;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
public boolean isEngineer() {
return isEngineer;
}
public void setEngineer(boolean isEngineer) {
this.isEngineer = isEngineer;
}
public User(){}
public User(String name, int age, String company, boolean isEngineer){
this.name = name;
this.age = age;
this.company = company;
this.isEngineer = isEngineer;
}
}
5、运行结果
(1)通过 http://localhost:8080/打开:
(2)通过 http://www.corsdemo.com:8080/ 打开:
结论
客户端通过 http://www.corsdemo.com:8080/DemoCORS.html 或 http://localhost:8080/DemoCORS.html 均可以实现 CORS 跨域访问。
注意事项
1、Access-Control-Allow-Origin 不支持连续设置以逗号分隔的多个域名,如:"domain1.com,domain2.com";
2、请求头的 Origin 由浏览器自动指定,不可手动更改,但可以通过 request.getHeader("origin") 读取该值;
3、站点外打开网页文件,请求头的 Origin 为 null。例如在本地磁盘任意位置直接双击打开 DemoCORS.html,url 显示为:file:///E:/Java/DemoCORS.html,单击后 Origin 为 null,本例对这种情况也允许访问,因此可以正常显示数据。否则控制台会提示同源策略限制: