详解如何使用Nginx解决跨域问题


Posted in Servers onMay 06, 2022

先来说一下什么是同源策略

同源(域名、协议、端口相同)策略是一种约定,是浏览器最核心也是最基本的安全功能,如果缺少了同源策略,浏览器的正常功能将受到影响。

什么是跨域?

跨域就是跨域名,跨端口,跨协议(非同源策略)。

跨域分类

简单说,跨域分为 简单跨域复杂跨域

简单跨域:不会发送OPTIONS请求。

复杂跨域:会发送一个预检查OPTIONS请求。

复杂跨域的条件是:

①、非GET、HEAD、POST请求。

②、POST请求的Content-Type不是application/x-www-form-urlencoded, multipart/form-data, 或text/plain。

③、添加了自定义header,例如Token。

跨域请求浏览器会在Headers中添加Origin,通常情况下不允许用户修改其值。

Nginx解决跨域问题

跨域是前后端分离开发中非常常见的问题。无论用什么编程语言,现在都已经很难离开Nginx。因此直接在Nginx中处理跨域问题有得天独厚的优势。当出现跨域问题的时候,只需要给Nginx服务器配置响应的header参数即可。

只需要在Nginx的配置文件中配置以下参数:

location / { ``  ``add_header Access-Control-Allow-Origin *;``  ` `  ``add_header ``'Access-Control-Allow-Credentials'` `'true'``; ``# 是否允许后续请求携带cookies,该值只能是true,否则不返回。如果上面的Access-Control-Allow-Origin设置的是* 而你又需要cookie信息,则 必须设置这行。``  ` `  ``add_header Access-Control-Allow-Methods ``'GET, POST, OPTIONS'``;``  ` `  ``add_header Access-Control-Allow-Headers *;` `  ``if` `($request_method = ``'OPTIONS'``) {``    ``return` `204;``  ``}``}

上面的配置代码即可解决跨域问题了,不想深入研究的,看到这里就可以了=-=

解释

1、Access-Control-Allow-Origin

服务器默认是不被允许跨域的。给Nginx配置Access-Control-Allow-Origin * 后,表示服务器可以接受所有的请求源(Origin),即接受所有跨域的请求。也就是说,表示接受任意域名的请求。上面我们这里设置的是* 这是最简单粗暴的方式,但是服务器出于安全考虑,肯定不会这么干,而且,如果是*的话,游览器将不会发送cookies数据(如果需要携带cookies数据,则需要设置 'Access-Control-Allow-Credentials:true')。

所以Access-Control-Allow-Origin一般都是设置为 指定域(也就是指定 某一个url来请求我服务器)的方式。指定域 设置的方式如下:

add_header Access-Control-Allow-Origin 'www.test.com'; 注意:只能指定一个域

2、Access-Control-Allow-Headers 是为了防止出现以下错误:

Request header field Content-Type is not allowed by Access-Control-Allow-Headers in preflight response.

这个错误表示当前请求Content-Type的值不被支持。其实是我们发起了"application/json"的类型请求导致的。这里涉及到一个概念:预检请求(preflight request)。请看下面"预检请求"的介绍。

3、Access-Control-Allow-Methods 是为了防止出现以下错误:

Content-Type is not allowed by Access-Control-Allow-Headers in preflight response.

4、给OPTIONS 添加 204的返回,是为了处理在发送POST请求时Nginx依然拒绝访问的错误

发送"预检请求"时,需要用到方法OPTIONS,所以服务器需要允许该方法。

预检请求(preflight request)

其实上面的配置涉及到了一个W3C标准:CROS,全称是跨域资源共享 (Cross-origin resource sharing),它的提出就是为了解决跨域请求的。

跨域资源共享(CORS)标准新增了一组HTTP 首部字段,允许服务器声明哪些源站有权限访问哪些资源。另外,规范要求,对那些可能对服务器数据产生副作用的HTTP 请求方法(特别是 GET 以外的 HTTP 请求,或者搭配某些 MIME 类型的 POST 请求),浏览器必须首先使用 OPTIONS 方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求。服务器确认允许之后,才发起实际的 HTTP 请求。在预检请求的返回中,服务器端也可以通知客户端,是否需要携带身份凭证(包括 Cookies 和 HTTP 认证相关数据)。

其实Content-Type字段的类型为application/json的请求 就是上面所说的搭配某些 MIME 类型的 POST 请求,CORS规定,Content-Type不属于以下MIME类型的,都属于预检请求:

application``/x-www-form-urlencoded``multipart``/form-data``text``/plain

POST请求中的Content-Type不是上面这三种的其中一种的话,都属于预检请求。(上面也有提到过,就是 复杂跨域的条件中的第②步)

所以 application/json的请求 会在正式通信之前,增加一次"预检"请求,这次"预检"请求会带上头部信息 Access-Control-Request-Headers: Content-Type:

OPTIONS /api/test HTTP/1.1``Origin: http://foo.example``Access-Control-Request-Method: POST``Access-Control-Request-Headers: Content-Type``... 省略了一些

服务器回应时,返回的头部信息如果不包含Access-Control-Allow-Headers: Content-Type则表示不接受非默认的的Content-Type。

即出现以下错误:

Request header field Content-Type is not allowed by Access-Control-Allow-Headers in preflight response.

尾声

解决跨域的解决方案有很多种,最常见也是最传统的解决方式是使用JSONP的方式。CORS与JSONP的使用目的相同,但是比JSONP更强大。

JSONP只支持GET请求,CORS支持所有类型的HTTP请求。JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。

到此这篇关于如何使用Nginx解决跨域问题的文章就介绍到这了!


Tags in this post...

Servers 相关文章推荐
nginx 防盗链防爬虫配置详解
Mar 31 Servers
Nginx缓存设置案例详解
Sep 15 Servers
Apache Linkis 中间件架构及快速安装步骤
Mar 16 Servers
nginx刷新页面出现404解决方案(亲测有效)
Mar 18 Servers
nginx.conf配置文件结构小结
Apr 08 Servers
nginx配置之并发频次限制
Apr 18 Servers
使用 Docker Compose 构建复杂的多容器App
Apr 30 Servers
winserver2019安装软件一直卡在应用程序正在为首次使用做准备
Jun 10 Servers
Apache POI操作批量导入MySQL数据库
Jun 21 Servers
Apache Kafka 分区重分配的实现原理解析
Jul 15 Servers
Nginx如何限制IP访问只允许特定域名访问
Jul 23 Servers
ubuntu如何搭建vsftpd服务器
Dec 24 Servers
配置nginx负载均衡
May 06 #Servers
tomcat下部署jenkins的方法
排查Tomcat进程假死的问题
May 06 #Servers
使用Nginx的访问日志统计PV与UV
Tomcat配置访问日志和线程数
May 06 #Servers
tomcat正常启动但网页却无法访问的几种解决方法
May 06 #Servers
tomcat默认最大连接数及相关调整方法
May 06 #Servers
You might like
php中的时间显示
2007/01/18 PHP
PHP 使用redis简单示例分享
2015/03/05 PHP
php+mysql+ajax实现单表多字段多关键词查询的方法
2017/04/15 PHP
php通过pecl方式安装扩展的实例讲解
2018/02/02 PHP
Aliyun Linux 编译安装 php7.3 tengine2.3.2 mysql8.0 redis5的过程详解
2020/10/20 PHP
jQuery Dialog 弹出层对话框插件
2010/08/09 Javascript
jQuery 源码分析笔记(2) 变量列表
2011/05/28 Javascript
JavaScript格式化日期时间的方法和自定义格式化函数示例
2014/04/04 Javascript
基于JQuery打造无缝滚动新闻步骤详解
2016/03/31 Javascript
jQuery布局组件EasyUI Layout使用方法详解
2017/02/28 Javascript
JavaScript阻止表单提交方法(附代码)
2017/08/15 Javascript
javascript如何用递归写一个简单的树形结构示例
2017/09/06 Javascript
vue2.0 + ele的循环表单及验证字段方法
2018/09/18 Javascript
详解vue服务端渲染浏览器端缓存(keep-alive)
2018/10/12 Javascript
Vue仿微信app页面跳转动画效果
2019/08/21 Javascript
layui use 定义js外部引用函数的方法
2019/09/26 Javascript
AI小程序之语音听写来了,十分钟掌握百度大脑语音听写全攻略
2020/03/13 Javascript
html+vue.js 实现漂亮分页功能可兼容IE
2020/11/07 Javascript
[04:52]第二届DOTA2亚洲邀请赛主赛事第一天比赛集锦:OG娜迦海妖放大配合谜团大中3人
2017/04/02 DOTA
[39:08]完美世界DOTA2联赛PWL S3 LBZS vs CPG 第一场 12.12
2020/12/16 DOTA
Python+OpenCV图片局部区域像素值处理详解
2019/01/23 Python
Python3.5基础之NumPy模块的使用图文与实例详解
2019/04/24 Python
PyQt5 QTable插入图片并动态更新的实例
2019/06/18 Python
详解Django模版中加载静态文件配置方法
2019/07/21 Python
Python实现二叉搜索树BST的方法示例
2019/07/30 Python
wxpython实现按钮切换界面的方法
2019/11/19 Python
Python和Sublime整合过程图示
2019/12/25 Python
CSS3实现渐变背景兼容问题
2020/05/06 HTML / CSS
德国香水、化妆品和护理产品网上商店:Parfumdreams
2018/09/26 全球购物
采购人员的个人自我评价
2014/01/16 职场文书
《大作家的小老师》教学反思
2014/04/16 职场文书
2016年教师师德师风承诺书
2016/03/25 职场文书
受欢迎的自荐信,就这么写!
2019/04/19 职场文书
2019年公司卫生管理制度样本
2019/08/21 职场文书
redis sentinel监控高可用集群实现的配置步骤
2022/04/01 Redis
MySQL 原理与优化之Update 优化
2022/08/14 MySQL