最近在学习http的相关知识,看到有关跨域的问题。平时工作中也会一直听到跨域问题,自己就深入的学习一下,这里记录一下,方便以后查阅。
1、为什么会出现跨域?
浏览器遵循同源政策(scheme(协议)
、host(主机)
和port(端口)
都相同则为同源
)。
非同源站点有这样一些限制:
- 不能读取和修改对方的 DOM
- 不读访问对方的 Cookie、IndexDB 和 LocalStorage
- 限制 XMLHttpRequest 请求。(后面的话题着重围绕这个)
当浏览器向目标 URl 发 Ajax 请求时,只要当前 URL 和目标 URL 不同源,则产生跨域,被称为跨域请求
。
2、解决方法
- JSONP
- CORS(跨域资源共享)
- Nginx
这里简单的介绍一下前两种方法:
【1】JSONP(参考文章)
JSONP 是服务器与客户端跨源通信的常用方法。最大特点就是简单适用,兼容性好(兼容低版本IE),缺点是只支持get请求,不支持post请求。
在HTML标签里,一些标签比如script、img这样的获取资源的标签是没有跨域限制的。
核心思想:网页通过添加一个<script>元素
,向服务器请求 JSON 数据,服务器收到请求后,将数据放在一个指定名字的回调函数的参数位置传回来。
【2】CORS(参考文章)
- 普通跨域请求:只需服务器端设置Access-Control-Allow-Origin
- 带cookie跨域请求:前后端都需要进行设置(前端设置:根据xhr.withCredentials字段判断是否带有cookie)
本篇主要介绍React项目中的解决办法:proxy与ngnix。
3、proxy
在package.json文件中使用proxy配置可以解决跨域问题.
"proxy":{ "/api":{ "target":"http://xxx.xxx.com", "changeOrigin": true, "pathRewrite": { "^/api": "" } } }
target
:接口的域名changeOrigin
:开启代理pathRewrite
:可以看到我使用了/api
来匹配请求接口的域名,而接口名称是/admin/login
,因此在实际请求中应该写成/api/admin/login
,但是我实际请求的地址又是没有api前缀的,因此需要通过pathRewrite重写地址,将接口请求的时候前缀去除。
4、nginx
上面的方式可以解决我们在React项目中开发环境的跨域问题,但是无法解决生产环境上的跨域问题(偶尔也会遇见) 。
- Mac安装nginx以及⚠️注意事项:请查看下篇文章
- 功能:
- http服务器,可以独立提供http服务;
- 虚拟主机:多个域名指向同一个服务器,服务器根据不同的域名把请求转发到不同的应用服务器;
- 反向代理:负载均衡,将请求转发至不同的服务器
3. 默认配置文件
location / {
root html; #文件根目录
index index.html index.htm; #默认起始页
}
4.修改配置文件
location / { root /Users/zhangsan/Documents/test/build; #直接指向打包后的文件 index index.html index.htm; } location /api { rewrite ^.+api/?(.*)$ /$1 break; proxy_pass http://XX.XXX.com; # 将地址代理到api上 }