-
浏览器有个同源策略(Same-0rigin Policy)
1、它规定了:默认情况下,AJAX请求只能发送给同源的URL
2、同源是指3个相同:协议、域名(IP)、端口
3、非同源的情况下,AJAX请求其实已经达到服务器,并且服务器的数据也到了浏览器,只是浏览器的同源策略将数据阻止了。

一般前后端不分离的项目以及前后端分离但是前端项目和后端项目放在同一个服务器域名下的不跨域,否则跨域。
下面我们来建一个前后端分离的项目验证跨域。
建后端项目










新建一个java文件UserServlet代码如下所示:
主要功能就是提供一个接口,返回一个json。
package com.jonas;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/users")
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("Application/json; charset=UTF-8");
StringBuilder sb = new StringBuilder();
sb.append("[");
sb.append("{\"name\":\"jonas\", \"age\":11},");
sb.append("{\"name\":\"jack\", \"age\":22},");
sb.append("{\"name\":\"bob\", \"age\":29},");
sb.append("{\"name\":\"李白\", \"age\":99},");
sb.append("{\"name\":\"杜甫\", \"age\":20}");
sb.append("]");
resp.getWriter().write(sb.toString());
}
}
启动Tomcat运行这个项目。
建前端项目


新建一个index.html文件代码如下:
主要功能是请求后端的users接口获得数据展示在页面上。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.0.js"></script>
</head>
<body>
<script>
$.getJSON("http://localhost:8080/CROS/users", (users)=> {
for (const user of users) {
$("body").append($(`<span>${user.name}</span>`));
$("body").append($(`<span>${user.age}</span>`));
}
});
</script>
</body>
</html>
点击右上角的浏览器图标,在浏览器打开这个页面。

可以看到运行后的地址还是localhost但是端口号变成63342了。

跨域
因为前端项目的端口号是63342,后端项目的端口号是8080,所以会出现跨域问题,检查浏览器,看到打印台报跨域错误。

查看网络请求,这个接口的请求头的origin就是源信息。这里表示请求是由http://localhost:63342发起的。

跨域资源共享
-
解决AJAX跨域请求的常用方法
CORS (Cross-0rigin Resource Sharing) ,跨域资源共享 -
CORS的实现需要客户端和服务器同时支持
1、客户端
所有的浏览器都支持(IE至少是IE10版本)
1、服务器
需要返回相应的响应头(比如Access-Control-Allow-0rigin),告知浏览器这是一个允许跨域访问的请求
为了让前端项目可以跨域访问后端的数据,我们为后端的响应增加头部信息
增加响应头resp.setHeader("Access-Control-Allow-Origin", "http://localhost:63342");
允许特定的源访问。
或者resp.setHeader("Access-Control-Allow-Origin", "*");
允许所有源访问。
修改后代码:
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 允许来自http://localhost:63342的请求跨域访问。
resp.setHeader("Access-Control-Allow-Origin", "http://localhost:63342");
resp.setContentType("Application/json; charset=UTF-8");
StringBuilder sb = new StringBuilder();
sb.append("[");
sb.append("{\"name\":\"jonas\", \"age\":11},");
sb.append("{\"name\":\"jack\", \"age\":22},");
sb.append("{\"name\":\"bob\", \"age\":29},");
sb.append("{\"name\":\"李白\", \"age\":99},");
sb.append("{\"name\":\"杜甫\", \"age\":20}");
sb.append("]");
resp.getWriter().write(sb.toString());
}
重新部署后再次访问,就不会报错了。
浏览器访问web流程
当浏览访问一个网页时,会向部署前端项目的服务器请求这个网页,前端服务器将网页内容返回给浏览器。
浏览器拿到网页的时候,网页内部如果有接口请求,会继续向后端服务器请求数据,后端服务器收到请求后再将数据返回给浏览器。

补充
-
虽然前端也有方法解决跨域问题,但是比较麻烦。一般都是后端来解决跨域问题。
-
这里说的跨域是指AJAX请求,如果是类似于
<img src='https://baidu.com?img=bd_logo.png' />
标签加载图片,或者是<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.0.js"></script>
下载js文件或者是下载CSS文件这种都不会跨域。
网友评论