同源策略

https://developer.mozilla.org/zh-CN/docs/Web/Security/Same-origin_policy

说明

同源策略,是现代浏览器普遍遵守的一个安全策略,能帮助阻隔恶意文档,减少可能被攻击的可能。

怎么样算同源?请求发送方的协议域名端口,与接收方的都一样,才算同源。

只要任意一个不一样,都算跨域,会报错误
image.png

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 失败 主机不同

产生原因-安全

image.png
1、用户访问应网站,输入账号密码登录
2、登录后银行网站返回给浏览器一个身份信息,存储在浏览器的cookie里面
3、用户访问不安全的网站
4、没有同源策略的话,不安全网站可以轻松获取cookie里的身份信息
5、不安全网站去登录银行,银行只认这个身份信息,以为是这个用户登录了
6、不安全网站可以操作这个用户的账号

限制

image.png
image.png

==================

跨域

image.png

产生原因

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

  1. <script src="https://unpkg.com/axios/dist/axios.min.js"></script>

比如引入某些第三方库js文件,不会受到限制。

JSONP的原理就是利用了script标签的这个特性

image.png
缺点:
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 头部允许浏览器和服务器相互了解,以确实请求或响应应该成功还是失败。
image.png
发送源,和服务器允许的发送源一致,那么浏览器就会放通,不会报错。相当于服务器告诉浏览器,我同意这样的源访问我。

Access-Control-Allow-Origin 头部,是服务器端设置的;或者允许所有的源,可以设置成”*”。

  1. 服务器需要设置header
  2. Access-Control-Allow-Origin: http://127.0.0.1:3000
  3. Access-Control-Allow-Origin:* 表示所有人都能直接获取

预检请求

CORS 通过一种叫预检请求(preflighted request)的服务器验证机制,允许使用自定义头部、除 GET和 POST 之外的方法,以及不同请求体内容类型。

在要发送涉及上述某种高级选项的请求时,会先向服务器发送一个“预检”请求。

发送方,请求使用 OPTIONS 方法发送并包含以下头部。
 Origin:与简单请求相同。
 Access-Control-Request-Method:请求希望使用的方法。
 Access-Control-Request-Headers:(可选)要使用的逗号分隔的自定义头部列表。

  1. "Content-type"="application/x-www-form-urlencoded"

服务器方,需要设置:
 Access-Control-Allow-Origin:与简单请求相同。
 Access-Control-Allow-Methods:允许的方法(逗号分隔的列表)。
 Access-Control-Allow-Headers:服务器允许的头部(逗号分隔的列表)。
 Access-Control-Max-Age:缓存预检请求的秒数。

  1. Access-Control-Allow-Origin: http://127.0.0.1:3000
  2. Access-Control-Allow-Methods: POST, GET
  3. Access-Control-Allow-Headers: myheader
  4. Access-Control-Max-Age: 1728000

例子:

  1. res.header("Access-Control-Allow-Origin","http://localhost:8000");
  2. res.header("Access-Contro1-Allow-Credentials", true);
  3. res.header("Access-Control-Allow-Headers","content-type", "content-length", "Authorization", "Accept","X-Requested-with");
  4. res header("Access-Control-Allow-Methods","PUT, POST, GET, DELETE, HEAD, OPTIONS")
  5. if (req.method ==="OPTIONS"){
  6. res.send(OK! )
  7. return
  8. }

凭据请求

默认情况下,跨源请求不提供凭据(cookie、HTTP 认证和客户端 SSL 证书)。

发送方,可以通过将withCredentials 属性设置为 true 来表明请求会发送凭据。

服务器方,可以设置接收cookie等凭证

  1. Access-Control-Allow-Credentials: true

缺点

1、服务器的Access-Control-Allow-Origin 设置写1个,或者,写就不允许携带cookie(为了保证安全)

3、http proxy(开发时常用)

通过前端打包工具配置http-proxy,改变我们发送的源Origin(协议、域名、端口),自动改为和服务器一样的源Origin(协议、域名、端口),这样服务器的响应,浏览器就识别为同源,而非跨域。

只在开发时有效,打包生产环境后,部署到服务器上是不起作用的。

webpack
image.png

vite2
官方介绍:https://cn.vitejs.dev/config/#server-proxy,比较模糊

自己配置 vite.config.js 如下:

  1. import { defineConfig } from 'vite'
  2. import vue from '@vitejs/plugin-vue'
  3. import path from 'path'
  4. // 定义 vite 的配置
  5. export default defineConfig(({ command }) => {
  6. return {
  7. resolve: {
  8. // 路径别名
  9. alias: {
  10. '@': path.resolve(__dirname, 'src'),
  11. }
  12. },
  13. // 服务器选项
  14. server: {
  15. // http-proxy 代理,原理是改变其他电脑发送请求头RequestHeader的源Origin,
  16. // 使得每台电脑的源Origin = 服务器端设置的响应头ResponseHeader的 Access-Control-Allow-Origin 属性,
  17. // 浏览器就不会因为安全问题而报错
  18. proxy: {
  19. // 固定写法,如果写成'/'会导致Error: socket hang up
  20. '/api': {
  21. // target: 'http://你的前端服务器IP:前端服务器端口'
  22. target: 'http://192.168.0.185:3000',
  23. // 是否改变每台访问前端服务器的浏览器的源Origin?true为改变
  24. changeOrigin: true,
  25. // 固定写法,因为上面写了/api,实际上我们的请求都不带api,这里要替换掉
  26. rewrite: (path) => path.replace(/^\/api/, '')
  27. },
  28. }
  29. },
  30. plugins: [
  31. vue(),
  32. ],
  33. };
  34. });

注意!!!最后请求的基本路径,要设置为上面写的/api,这样才能使用代理,否则上面设置是没有效果的。
image.png

优点

1、支持post请求
2、不需要服务器再额外设置,但是还是要设置 Access-Control-Allow-Origin 属性 = 前端服务器的ip和端口
image.png(图为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

只能实现一个主域和其他子域的操作
image.png

8、window.name + iframe