一、什么是跨域?
1.同源策略及其限制内容
同源策略是一种约定,它是浏览器最核心也是最基本的安全功能,如果缺少了同源策略,浏览器很容易收到
XSS、CSRF等攻击。所谓同源值得是 “协议”+“域名”+“端口” 三者相同,即便两个不同的域名指向同一个ip地址,也非同源。
1.1XSS攻击
XSS 攻击,即跨站脚本攻击(Cross Site Scripting),它是 web 程序中常见的漏洞。 在输入的时候会出现一些不必要的字段。
原理:
攻击者往 web 页面里插入恶意的 HTML 代码(Javascript、css、html 标签等),当用户浏览该页面时,嵌入其中的 HTML 代码会被执行,从而达到恶意攻击用户的目的。如盗取用户 cookie 执行一系列操作,破坏页面结构、重定向到其他网站等
预防 (也就是在执行查询的时候浏览器执行的一些代码的过滤)
完整的过滤体系可以做到预防XSS的攻击(需要对用户的输入进行处理,只允许输入合法的值,其它值一概过滤掉)
1.2 CSRF攻击
攻击者盗用你的名字,以你的名义发送而已请求,这个请求在浏览器看来是合法的的但是却完成了攻击者所期望的一个操作,A是存在CSRF漏洞的网站,B是攻击者创建的恶意网站,C是A网站的合法用户。 这之间的关联(借刀偷袭)
原理
- 用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A;
2.在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登录网站A成功,可以正常发送请求到网站A;
-
用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B;
-
网站B接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问第三方站点A;
-
浏览器在接收到这些攻击性代码后,根据网站B的请求,在用户不知情的情况下携带Cookie信息,向网站A发出请求。网站A并不知道该请求其实是由B发起的,所以会根据用户C的Cookie信息以C的权限处理该请求,导致来自网站B的恶意代码被执行。
预防
对“用户凭证”进行校验处理,通过这种机制可以对用户的请求是合法进行判断,判断是不是跨站攻击的行为。因为“用户凭证”是Cookie中存储的,所以防护机制的处理对像也是Cookie的数据,我们要在防护的数据中加入签名校验,并对数据进行生命周期时间管理,就是数据过期管理
同源策略限制的内容
- Cookie、LocalStorage、IndexedDB 等存储性内容
- DOM 节点
- AJAX 请求发送后,结果被浏览器拦截了
允许跨域加载资源的标签
<img src=XXX>
<link href=XXX>
<script src=XXX>
二、跨域解决方案
1.jsonp
(1)JSONP原理
利用 <script>
标签没有跨域限制的漏洞,网页可以得到从其他来源动态产生的 JSON 数据。JSONP请求一定需要对方的服务器做支持才可以。
(2)JSONP优缺点
JSONP优点是简单兼容性好,可用于解决主流浏览器的跨域数据访问的问题。缺点是仅支持get方法具有局限性,不安全可能会遭受XSS攻击
2.cors
CORS需要浏览器和后端同时支持。IE8和9需要通过XDomainRequest来实现
浏览器会自动进行 CORS 通信,实现 CORS 通信的关键是后端。只要后端实现了 CORS,就实现了跨域
服务端设置 Access-Control-Allow-Origin 就可以开启 CORS。 该属性表示哪些域名可以访问资源,如果设置通配符则表示所有网站都可以访问资源
通过这个实现跨域会出现两种情况(简单请求、复杂请求)
(1)简单请求(gGET、HEAD、POST)
<script src="https://cdn.bootcss.com/axios/0.19.2/axios.min.js"></script>
<script>
axios.get("http://127.0.0.1:8080/api/corslist");
</script>
复制代码
(2)复杂请求(会多出两个不一样的头部请求Access-Control-Request-Method、Access-Control-Request-Headers)
除了这两个请求还会多出三个头部
-
Access-Control-Allow-Methods:允许访问的方式
-
Access-Control-Allow-Headers:允许携带的头
-
Access-Control-Max-Age:本次许可的有效时长,单位是秒,过期之前的ajax请求就无需再次进行预检了
这里我们加入了一个非集合内的header
头cc
来达到非简单请求的目的
<script src="https://cdn.bootcss.com/axios/0.19.2/axios.min.js"></script>
<script>
axios.get("http://127.0.0.1:8080/api/corslist", { header: { cc: "xxx" } });
</script>
复制代码
3.a.cli工具中的代理
1)Webpack(4.x)
在webpack中可以配置proxy来快速获得接口道理的能力。
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: {
index: "./index.js"
},
output: {
filename: "bundle.js",
path: path.resolve(__dirname, "dist")
},
devServer: {
port: 8000,
proxy: {
"/api": {
target: "http://localhost:8080"
}
}
},
plugins: [
new HtmlWebpackPlugin({
filename: "index.html",
template: "webpack.html"
})
]
};
复制代码
2)Vue-cli2.X
// config/index.js
...
proxyTable: {
'/api': {
target: 'http://localhost:8080',
}
},
...
复制代码
3)Vue-cli 3.x
// vue.config.js 如果没有就新建
module.exports = {
devServer: {
port: 8000,
proxy: {
"/api": {
target: "http://localhost:8080"
}
}
}
};
复制代码
4)Parcel(2.x)
// .proxyrc
{
"/api": {
"target": "http://localhost:8080"
}
}
复制代码