-
URL的组成部分?
示例:http://www.example.com:80/path/to/myfile.html?key1=value1&key2=value2#SomewhereInTheDocument
- 协议:http://
- 域名:www.example.com
- 端口::80
- 请求路劲:/path/to/myfile.html
- 请求参数:?key1=value1&key2=value2
- 瞄点:#SomewhereInTheDocument
-
什么是跨域?
-
**(广义说)**是指一个域下的文档或脚本试图去请求另一个域下的资源
-
**(狭义说)**是由浏览器同源策略限制的一类请求场景
浏览器同源策略/SOP(Same Origin Policy):
- 是浏览器最核心也最基本的安全功能。
- 必须是协议、域名、端口完全一致的才符合同源策略。
- 缺少同源策略,浏览器很容易受到XSS、CSFR等攻击。
-
-
常见跨域场景?
-
同一域名,不同文件或路劲,允许通信
http://www.athen.com/a.js
http://www.athen.com/b.js
http://www.athen.com/lib/c.js
-
同一域名,不同端口,不允许通信
http://www.athen.com:8080/a.js
http://www.athen.com:8081/b.js
-
同一域名,不同协议,不允许通信
http://www.athen.com/a.js
https://www.athen.com/b.js
-
域名和域名IP,不允许通信
http://www.athen.com/a.js
https://192.168.17.12/b.js
-
主域名相同,子域名不同,不允许通信
http://www.athen.com/a.js
http://xxx.athen.com/b.js
-
不同域名,不允许通信
http://www.athenone.com/a.js
http://www.athentwo.com/b.js
-
-
跨域解决方案
- 通过Jsonp跨域
- vite配置文件代理
- Nginx代理
- 跨域资源共享(CORS)
一、Jsonp跨域(通过动态创建script,在请求一个带参网址实现跨域通信,缺点:只能实现GET一种请求)
原生实现:
<script> let script = document.createElement('script'); script.type = 'text/javascript'; // 传参并指定回调函数为onCallBack script.src = 'http://www.athen.com:8080/login?user=admin&callBack=onCallBack'; document.head.appendChild(script); // 回调函数 const onCallBack = (val) => { console.log(JSON.stringify(val)) } </script> // 服务端返回如下(返回时执行全局函数) // onCallBack({"status":true,"user":"admin"})
JQquery实现:
$.ajax({ url:"http://www.athen.com:8080/login", type:'get', // 请求类型GET dataType:'jsonp', // 请求方式为jsonp jsonpCallBack:'onCallBack', // 自定义回调函数名 data:{} // 携带数据 });
Node.js实现:
const qs = require("qs"); const http = require("http"); const server = http.createServer(); server.on('request',(req,res) => { let params = qs.parse(req.url.split("?")[1]); let fn = params.callback; // jsonp返回设置 res.writeHead(200,{"Content-Type":"text/javascript"}); res.write(fn + "(" + qs.stringify(params) + ")"); res.end(); }) server.listen("8080");
二、Vite配置文件代理
server: {
cors: true, // 默认启用并允许任何源
host: "172.168.17.93", // 设置启动IP
prot: 8080, // 设置启动端口
proxy: {
'/ngshop': {
target: 'http://172.168.18.122:8080', // 代理地址
changeOrigin: true, // 跨域
rewrite: (path) => path.replace(/^\/ngshop/, '') // 替换掉api前缀 防止多个api地址
}
},
hmr: {
overlay: true,
},
},
三、Nginx代理
location /{
rewrite ^.+api/?(.*)$ /$1 break; #移除api前缀
proxy_pass url; #url: 指请求地址
root html; #html: 指html路径
}
四、CORS
- 普通跨域请求:服务端设置Access-Control-Allow-Origin即可,前端无须设置。
- 带cookie请求:前后端都需要设置字段。
let xhr = new XMLHttpRequest(); xhr.withCredentials = true; // 前端设置是否带cookie xhr.open("post","http://www.athen.com:8080/login",true); xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); xhr.send("user=admin"); xhr.onreadystatechange = () => { if(xhr.readyState == 4 && xhr.status == 200){ console.log(xhr.responseText) } }