如何使用Nginx解决跨域问题详解
先来说一下什么是同源策略
同源(域名、协议、端口相同)策略是一种约定,是浏览器最核心也是最基本的安全功能,如果缺少了同源策略,浏览器的正常功能将受到影响。
什么是跨域?
跨域就是跨域名,跨端口,跨协议(非同源策略)。
跨域分类
简单说,跨域分为 简单跨域 和 复杂跨域。
简单跨域:不会发送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') { return204; } }
上面的配置代码即可解决跨域问题了,不想深入研究的,看到这里就可以了=-=
解释
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解决跨域问题的文章就介绍到这了,更多相关Nginx解决跨域内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
Nginx CertBot配置HTTPS泛域名证书Debian及常见问题
这篇文章主要介绍了Nginx CertBot配置HTTPS泛域名证书Debian及常见问题解决,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪2023-11-11强大的 Web 应⽤服务器OpenResty安装(Nginx仓库)
OpenResty 是⼀个强大的 Web 应⽤服务器,Web 开发⼈员可以使用 Lua 脚本语⾔调动 Nginx ⽀持的各种 C 以及 Lua 模块,更主要的是在性能方面,OpenResty可以快速构造出足以胜任 10K 以上并发连接响应的超高性能 Web 应用系统2023-06-06
最新评论