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


    关于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;
    }
    
    • 1
    • 2
    • 3

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

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

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

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

    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;
        }         
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前。因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担。添加下方名片,即可获取全套学习资料哦

  • 相关阅读:
    如何评测一个大模型?(微软亚洲研究院 )
    Java8-17 --- idea2022
    决策树模型(3)决策树的生成与剪枝
    谁选谁尴尬的IB课程介绍
    C++入门基础(上)
    17_数据结构与算法
    24.Python文件I/O(二)【异常处理&断言assert】
    病毒攻防原理
    MySQL知识总结 (六) MySQL调优
    NFT平台开发:NFT数字馆藏平台开发
  • 原文地址:https://blog.csdn.net/m0_61083409/article/details/126080959