详解如何使用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实现反向代理
Sep 20 Servers
Centos7.7 64位利用本地完整安装包安装lnmp/lamp套件教程
Mar 09 Servers
Nginx快速入门教程
Mar 31 Servers
Nginx开启Brotli压缩算法实现过程详解
Mar 31 Servers
详解nginx location指令
Jan 18 Servers
Nginx中使用Lua脚本与图片的缩略图处理的实现
Mar 18 Servers
如何开启Apache,Nginx和IIS服务器的GZIP压缩功能
Apr 29 Servers
Tomcat弱口令复现及利用
May 06 Servers
Tomcat 与 maven 的安装与使用教程
Jun 16 Servers
git stash(储藏)的用法总结
Jun 25 Servers
nginx配置指令之server_name的具体使用
Aug 14 Servers
码云(gitee)通过git自动同步到阿里云服务器
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输出金字塔的2种实现方法
2014/12/16 PHP
54个提高PHP程序运行效率的方法
2015/07/19 PHP
PHP Header用于页面跳转时的几个注意事项
2016/10/21 PHP
Zend Framework框架实现类似Google搜索分页效果
2016/11/25 PHP
PHP PDOStatement::bindValue讲解
2019/01/30 PHP
从父页面读取和操作iframe中内容方法
2009/07/25 Javascript
Firefox中beforeunload事件的实现缺陷浅析
2012/05/03 Javascript
jquery 倒计时效果实现秒杀思路
2013/09/11 Javascript
浅谈checkbox的一些操作(实战经验)
2013/11/20 Javascript
JavaScript的21条基本知识点
2014/03/04 Javascript
javascript浏览器兼容教程之事件处理
2014/06/09 Javascript
两种方法实现在HTML页面加载完毕后运行某个js
2014/06/16 Javascript
JS中处理时间之setUTCMinutes()方法的使用
2015/06/12 Javascript
小程序开发实战:实现九宫格界面的导航的代码实现
2017/01/19 Javascript
vue-cli+webpack记事本项目创建
2017/04/01 Javascript
基于jQuery对象和DOM对象和字符串之间的转化实例
2017/08/08 jQuery
vue watch自动检测数据变化实时渲染的方法
2018/01/16 Javascript
vue实现购物车抛物线小球动画效果的方法详解
2019/02/13 Javascript
node.js使用express框架进行文件上传详解
2019/03/03 Javascript
ES6 新增的创建数组的方法(小结)
2019/08/01 Javascript
[01:13:17]Secret vs NB 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
[01:04:05]Mineski vs TNC 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/16 DOTA
Python实现Linux命令xxd -i功能
2016/03/06 Python
详解django中自定义标签和过滤器
2017/07/03 Python
Python实现将Excel转换成xml的方法示例
2018/08/25 Python
Python实现将Excel转换成为image的方法
2018/10/23 Python
对python条件表达式的四种实现方法小结
2019/01/30 Python
分享8款纯CSS3实现的搜索框功能
2017/09/14 HTML / CSS
css3打造一款漂亮的卡哇伊按钮
2013/03/20 HTML / CSS
一分钟演讲稿
2014/04/30 职场文书
2014年自愿离婚协议书范本
2014/09/25 职场文书
社区党建工作汇报材料
2014/10/27 职场文书
结婚典礼致辞
2015/07/28 职场文书
合作意向书怎么写
2019/06/24 职场文书
某学校的2019年度工作报告范本
2019/10/11 职场文书
pandas数值排序的实现实例
2021/07/25 Python