关于Nginx跨域配置的一些问题,详解如何正确的配置跨域

本文详细介绍了Nginx跨域配置的相关问题,包括跨域请求的原因、类型以及浏览器处理方式。重点讨论了非简单请求在实际应用中可能遇到的token验证陷阱,并提出了两种解决方案,尤其是推荐正确配置Nginx以处理OPTIONS预检请求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关于Nginx跨域配置的一些问题

首先说说跨域请求

为什么跨域请求的时候浏览器会报错,拿不到服务器返回的结果?

跨域不是请求发不出去,而是服务端正常返回结果后被浏览器拦截了返回结果。(浏览器为了防止非同源的请求 拿到服务器的返回数据结果)

什么是跨域请求?

凡是请求来源与请求目标的协议(如http和https)、域名(如a.b.com和b.b.com)、端口号不同(如a.com:80和a.com:81)的请求,都是跨域请求。

跨域请求举例:

从http://a.com 请求 https://a.com

从http://a.a.com 请求 http://b.a.com

从http://a.com:80 请求http://a.com:81

都是跨域请求。

跨域请求的类型
1、简单请求

请求方法只能是:HEAD、GET、POST

能主动自定义设置的头信息只能包括:Accept、Accept-Language、Content-Language、Last-Event-ID、Content-Type

其中Content-Type只能限定三个值:application/x-www-form-urlencoded、multipart/form-data、text/plain

2、非简单请求

不能同时满足简单请求的两个条件的都是非简单请求。例如:

请求方法为PUT,DELETE

请求方法为POST,但是Content-Type值是application/json

请求的头信息里面自定义了属性X-Token、Authorization等

这些都是非简单请求。

3、浏览器对简单请求和非简单请求的处理方式

1、对于简单请求:浏览器会在 请求头信息里增加一个Origin字段,表明本次请求的来源,服务器返回的头部信息里需包含 Access-Control-Allow-Origin,并包含Origin值,则浏览器才能正常返回数据,否则出现跨域错误。

2、对于非简单请求:浏览器会分成2步处理:①预检(preflight)请求 + ②简单请求

①:真正请求前增加一次预检(preflight)请求,请求方法是OPTIONS,浏览器进行校验,如果返回状态码是2XX(通常是204)表示验证通过

②:预检请求通过后,浏览器向服务器发送简单请求。

通过和Response里的相对应的内容进行对比,进行预检请求校验,例如Access-Control-Allow-Origin和Origin是否匹配;返回PUT,DELETE,请求的是PUT,则校验通过。

跨域请求容易遇到的问题

对于新手来说,服务器的跨域配置,都是面向谷歌,百度编程,例如nginx跨域配置,网上一大堆,直接拿过来就用了。对于简单请求,一般不会出现什么问题。但是对于非简单请求,就容易踩坑了。因为很多配置对于复杂的需求场景,或者说对于自己的特定的需求场景,并不完整或者说是适合的。

举个例子来说明:

例如我们做API开发的场景,或者前后端分离的场景,token验证登录。

通常简单流程是:

客户端请求登录->

服务器验证用户名密码->

通过后返回一个token->

客户端每次携带token向服务器请求数据->

服务器端校验token决定是否返回数据。

那么我们假设,客户端是通过自定义header的Authorization携带token向服务器请求数据,很明显这是一个非简单请求,那么浏览器首先会向服务器发送一个预检请求(上面说了请求的方法是OPTIONS),那么服务器端在接收到这个OPTIONS请求之后,如果不做判断处理,那么请求直接会被转发到应用里面。因为预检请求是不会携带token的,那么应用校验token的时候,必然就校验失败,返回xxx错误。这时候问题就出现了,浏览器预检请求校验就失败了,从而导致跨域错误。

为了解决这个问题,通常有2个方式

1、正确的配置跨域,判断OPTIONS请求(推荐)

if ($request_method = 'OPTIONS') {
	return 204;
}

2、应用里面判断OPTIONS请求(让应用更健壮)

//以PHP的TP框架为例
if($request->isOptions()) {
	return json([],204);
}

Nginx正确的跨域配置

server 级

add_header Access-Control-Allow-Credentials true; #是否携带cookie
add_header Access-Control-Allow-Origin $http_origin; #如果配置所有来源会有安全性问题,所以这里可以指定来源,如:xxx.xxx.com
add_header Access-Control-Allow-Methods $http_access_control_request_method; #允许的请求类型
add_header Access-Control-Allow-Headers $http_access_control_request_headers; #允许的header
add_header Access-Control-Max-Age 1728000; #在此时间内不在发送预检请求
#判断请求类型
if ($request_method = 'OPTIONS') {
	return 204;
}

location 级(引用优快云博主「懒的去其」的配置)

add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Origin $http_origin;    
              
location /file {
    if ($request_method = 'OPTIONS') {
       		add_header Access-Control-Allow-Origin $http_origin;
            add_header Access-Control-Allow-Methods $http_access_control_request_method;
            add_header Access-Control-Allow-Credentials true;
            add_header Access-Control-Allow-Headers $http_access_control_request_headers;
            add_header Access-Control-Max-Age 1728000;
            return 204;
    }         
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值