0. 前言
-
此文为88岁高龄、入门级前端初心者专用笔记;
-
暂时只关心 AJAX 请求受同源策略的影响及在 Vue 项目中的 解决方式 捏;
1. 必要性
1.0 你需要知道
(1)协议、域名、端口都相同,才为同源;
(2)浏览器报跨域错误,并不是服务器没有返回,而是服务器返回了,但是被浏览器拦截了。
(3)所谓的端口,其实可以简单地视作为进程 ID;端口的存在的就是因为服务器响应请求时需要找到具体的进程来响应,但是依靠进程 ID 又太过于依赖操作系统,每次都会发生变化而且无法通知想联系它的客户端,所以干脆统一安排一个窗口,让大家忽略细节,需要某类服务时就找那个窗口就行。
1.1 目的
同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据。
设想这样一种情况:A网站是一家银行,用户登录以后,又去浏览其他网站。如果其他网站可以读取A网站的 Cookie,会发生什么?
很显然,如果 Cookie 包含隐私(比如存款总额),这些信息就会泄漏。更可怕的是,Cookie 往往用来保存用户的登录状态,如果用户没有退出登录,其他网站就可以冒充用户,为所欲为。因为浏览器同时还规定,提交表单不受同源政策的限制。
由此可见,"同源政策"是必需的,否则 Cookie 可以共享,互联网就毫无安全可言了。
1.2 限制范围
目前,如果非同源,共有三种行为受到同源策略限制:
(1) Cookie、LocalStorage 和 IndexDB 无法读取。
(2) DOM 无法获得。
(3) AJAX 请求不能正常发送。
不受限制同源限制的:
(1) Form表单提交不受同源策略限制。
(2) 默认情况下的静态资源的获取。
静态资源是指在服务器端存储的不会变化的文件,如HTML、CSS、JavaScript、图片、音频、视频等文件。这些文件一般不包含动态内容,每次请求时返回的内容都是固定的。
在后端服务器中,可以设置特定的路由来处理静态资源的访问请求。例如,使用 Node.js 的 Express 框架可以使用 express.static 中间件来处理静态资源的请求。
将静态资源直接编辑放到服务器的指定目录下。当用户访问该服务器时,可以通过URL直接访问到这些静态资源。这种方法适用于小型项目或者对访问速度要求不高的场景。
前端本地图片 HTML <img />
就是获取静态资源的加载,默认情况下,请求不同源的静态资源不会有跨域问题,且浏览器是用 GET 请求获取的。
但 GET 请求是没有跨域这一说法的是错误的,只是上述情况不会有跨域问题,但在以下两种情况会有:
等获取静态资源标签的 crossOrigin 的属性不为 'use-credentials';
AJAX 发起的 GET 请求;
2. 解决方式
2.1 本地
2.1.1 代理服务器
开发时,npm run dev
等命令会在本地启动一个开发服务器;可以使用 vue.config.js
里的 devServer 配置开发服务器。
devServer: {
// host:'0.0.0.0', // 设置为您的 IP 地址,设置项目可用局域网 IP 地址访问
port: port,
proxy: {
"/api": {
target: process.env.VUE_APP_BASE_API,
changeOrigin: true,
pathRewrite: {
"^/api": "api"
}
}
// ...
1./api的作用
用代理首先你得有一个标识,表明请求路径中有这个标识的 ajax 请求要使用当前代理。
2.pathRewrite中 “^/api”:"xxx"的作用
当实际需要请求的路径里面没有“/api”时,就需要 pathRewrite,用"^/api":"",把"/api"去掉,这样既能有正确标识, 又能在请求到正确的路径。
2.1.2 配置后端接口地址
1. 在 .env.production
和 .env.development
中配置开发和生成环境的接口地址
VUE_APP_BASE_API = 'http://localhost:8003'
VUE_APP_BASE_API = 'http://xxxx:xxxx'
2. 在 request.js 中配置 ajax 请求的 baseURL
// 创建axios实例
const service = axios.create({
// axios中请求配置有 baseURL 选项,这样所有的请求都会自动加上该基础路径。
baseURL: process.env.VUE_APP_BASE_API
})
2.1.3 解决原理
在浏览器地址栏通过 URL 直接访问一个地址时,不存在跨域问题。
直接通过地址栏输入发起请求,对于服务器而言,这就是一个正常的浏览器请求,并不涉及到另一个域,也不存在一些脚本攻击,所以浏览器并不会对这种请求加以限制。
代理服务器解决 AJAX 请求时的跨域问题。
跨域,是当前域和目标服务域之间的,即在某个页面向后端发起请求时,才产生了跨域;
不配置代理,请求直接由浏览器发送给后台服务,不同源,产生跨域问题;
配置好 proxy 后,npm run dev ==> "dev": "vue-cli-service serve"
,webpack 在本地启动一个代理服务器,我们写的页面作为本地代理服务器上的静态资源,对目标服务器的请求会被代理中间件拦截转发。
// 模拟devServer配置代理后,前端文件及代理服务
const express = require('express');
const proxy = require('http-proxy-middleware');
const app = express();
// 对/api开头的请求进行转发处理
app.use(
'/api', //表示请求的接口以/api/开头
proxy({
target: 'http://localhost:8003', // 目标服务器
changeOrigin: true,
})
);
// 将前端项目所在的文件夹设置为静态资源
app.use('/', express.static('./index'));
app.listen(8013);
// proxy的路径匹配
// proxy({...}) - 匹配任意路径,所有的请求都会被代理。
// proxy('/', {...})-匹配任意路径,所有的请求都会被代理。
// proxy('/api', {...})-匹配所有以/api开始的路径。
2.3 远程服务器
浏览器 URL 访问 Web 应用的地址(部署所在服务器外网 IP + 对应协议 port)
前端文件部署在 Nginx 或 Tomcat 服务器上,Web 服务器配置允许跨域即可。
2.3.1 Tomcat
修改 web.xml ,都什么年代了还在前后端不分离部署!嗨呀是我们呀,但不管暂时看不懂捏。
2.3.2 Nginx
nginx.conf
location / {
# 目标地址
proxy_pass http://localhost:8003/;
# 设置是否允许 Cookie 传输
add_header Access-Control-Allow-Credentials true;
# 允许请求地址跨域 * 做为通配符
add_header Access-Control-Allow-Origin *;
# 允许跨域的请求方法
add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS';
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
if ($request_method = 'OPTIONS') {
return 204;
}
}
标签:Vue,浏览器,跨域,AJAX,api,proxy,服务器,请求
From: https://www.cnblogs.com/pupyy/p/18003540