同源策略
https://developer.mozilla.org/zh-CN/docs/Web/Security/Same-origin_policy
说明
同源策略,是现代浏览器普遍遵守的一个安全策略,能帮助阻隔恶意文档,减少可能被攻击的可能。
怎么样算同源?请求发送方的协议、域名、端口,与接收方的都一样,才算同源。
只要任意一个不一样,都算跨域,会报错误
和 http://store.company.com/dir/page.html 对比:
URL | 结果 | 原因 |
---|---|---|
http://store.company.com/dir2/other.html | 同源 | 只有路径不同 |
http://store.company.com/dir/inner/another.html | 同源 | 只有路径不同 |
https://store.company.com/secure.html | 失败 | 协议不同 |
http://store.company.com:81/dir/etc.html | 失败 | 端口不同 ( http:// 默认端口是80) |
http://news.company.com/dir/other.html | 失败 | 主机不同 |
产生原因-安全
1、用户访问应网站,输入账号密码登录
2、登录后银行网站返回给浏览器一个身份信息,存储在浏览器的cookie里面
3、用户访问不安全的网站
4、没有同源策略的话,不安全网站可以轻松获取cookie里的身份信息
5、不安全网站去登录银行,银行只认这个身份信息,以为是这个用户登录了
6、不安全网站可以操作这个用户的账号
限制
==================
跨域
产生原因
1、最开始没有前后端分离,前端写好HTML、CSS、JS,给到后端,整合到jsp、php等后端,放在同一个web服务器里面。
2、产生要求,实现异步无刷新操作,开始使用Ajax等技术,部署的时候还是同一个服务器,还不是跨域的。
3、但是开发的时候,前端和后端势必会分开的,否则前端还要懂后端的如Java等语言以及框架等知识,太难了
4、后面前端可以使用工具,创建本地服务器,此时本地是http:\127.0.0.1,和后端的接口域名(如baidu.com)不一致,就会产生跨域。
5、简单解决就是修改自己电脑的host,使得访问本地的http:\127.0.0.1,相当于访问后端接口,就实现不跨域了
6、再后来需要拆分服务器,如:
web服务器:静态资源
data服务器:数据,业务逻辑,数据分析
图片、视频等大型资源服务器
其他第三方开放接口
就会产生各种各样的域名,改host的方法就无法实现了。
跨域解决方案
1、JSONP
有的标签不存在跨域请求限制,如:
script
Img
link
iframe
等
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
比如引入某些第三方库js文件,不会受到限制。
JSONP的原理就是利用了script标签的这个特性
缺点:
1、func要是全局函数
2、需要服务器端支持
3、只能处理get请求
4、安全性不高
2、CORS 跨源资源共享
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS
(CORS,Cross-Origin Resource Sharing)定义了浏览器与服务器如何实现跨源通信。
CORS 是 HTTP 的一部分,它允许服务端来指定哪些主机可以从这个服务端加载资源。
CORS 背后的基本思路就是使用自定义的 HTTP 头部允许浏览器和服务器相互了解,以确实请求或响应应该成功还是失败。
发送源,和服务器允许的发送源一致,那么浏览器就会放通,不会报错。相当于服务器告诉浏览器,我同意这样的源访问我。
Access-Control-Allow-Origin 头部,是服务器端设置的;或者允许所有的源,可以设置成”*”。
服务器需要设置header:
Access-Control-Allow-Origin: http://127.0.0.1:3000
或
Access-Control-Allow-Origin:* 表示所有人都能直接获取
预检请求
CORS 通过一种叫预检请求(preflighted request)的服务器验证机制,允许使用自定义头部、除 GET和 POST 之外的方法,以及不同请求体内容类型。
在要发送涉及上述某种高级选项的请求时,会先向服务器发送一个“预检”请求。
发送方,请求使用 OPTIONS 方法发送并包含以下头部。
Origin:与简单请求相同。
Access-Control-Request-Method:请求希望使用的方法。
Access-Control-Request-Headers:(可选)要使用的逗号分隔的自定义头部列表。
"Content-type"="application/x-www-form-urlencoded"
服务器方,需要设置:
Access-Control-Allow-Origin:与简单请求相同。
Access-Control-Allow-Methods:允许的方法(逗号分隔的列表)。
Access-Control-Allow-Headers:服务器允许的头部(逗号分隔的列表)。
Access-Control-Max-Age:缓存预检请求的秒数。
Access-Control-Allow-Origin: http://127.0.0.1:3000
Access-Control-Allow-Methods: POST, GET
Access-Control-Allow-Headers: myheader
Access-Control-Max-Age: 1728000
例子:
res.header("Access-Control-Allow-Origin","http://localhost:8000");
res.header("Access-Contro1-Allow-Credentials", true);
res.header("Access-Control-Allow-Headers","content-type", "content-length", "Authorization", "Accept","X-Requested-with");
res header("Access-Control-Allow-Methods","PUT, POST, GET, DELETE, HEAD, OPTIONS")
if (req.method ==="OPTIONS"){
res.send(OK! )
return
}
凭据请求
默认情况下,跨源请求不提供凭据(cookie、HTTP 认证和客户端 SSL 证书)。
发送方,可以通过将withCredentials 属性设置为 true 来表明请求会发送凭据。
服务器方,可以设置接收cookie等凭证
Access-Control-Allow-Credentials: true
缺点
1、服务器的Access-Control-Allow-Origin 设置写1个,或者,写就不允许携带cookie(为了保证安全)
3、http proxy(开发时常用)
通过前端打包工具配置http-proxy,改变我们发送的源Origin(协议、域名、端口),自动改为和服务器一样的源Origin(协议、域名、端口),这样服务器的响应,浏览器就识别为同源,而非跨域。
只在开发时有效,打包生产环境后,部署到服务器上是不起作用的。
webpack
vite2
官方介绍:https://cn.vitejs.dev/config/#server-proxy,比较模糊
自己配置 vite.config.js 如下:
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
// 定义 vite 的配置
export default defineConfig(({ command }) => {
return {
resolve: {
// 路径别名
alias: {
'@': path.resolve(__dirname, 'src'),
}
},
// 服务器选项
server: {
// http-proxy 代理,原理是改变其他电脑发送请求头RequestHeader的源Origin,
// 使得每台电脑的源Origin = 服务器端设置的响应头ResponseHeader的 Access-Control-Allow-Origin 属性,
// 浏览器就不会因为安全问题而报错
proxy: {
// 固定写法,如果写成'/'会导致Error: socket hang up
'/api': {
// target: 'http://你的前端服务器IP:前端服务器端口'
target: 'http://192.168.0.185:3000',
// 是否改变每台访问前端服务器的浏览器的源Origin?true为改变
changeOrigin: true,
// 固定写法,因为上面写了/api,实际上我们的请求都不带api,这里要替换掉
rewrite: (path) => path.replace(/^\/api/, '')
},
}
},
plugins: [
vue(),
],
};
});
注意!!!最后请求的基本路径,要设置为上面写的/api,这样才能使用代理,否则上面设置是没有效果的。
优点
1、支持post请求
2、不需要服务器再额外设置,但是还是要设置 Access-Control-Allow-Origin 属性 = 前端服务器的ip和端口
(图为eggjs后端配置)
4、Nginx反向代理(生产环境常用)
用Linux 服务器安装Nginx,配置反向代理
不需要前端额外设置
https://www.yuque.com/yejielin/mypn47/ey4viu#pW4HB
5、postMessage
通过window.postMessage( ) 的方式,从一个窗口发送数据给另一个窗口
6、scoket io
web scoket协议跨域
7、document.domain iframe
只能实现一个主域和其他子域的操作