• Nginx跨域解决方案


    前置条件:
    前端网站地址:http://localhost:4443
    服务端网址:http://localhost:9081

    当网站8080访问服务端接口的时候会产生跨域的问题

    跨域主要设计到4个响应头:

    • Access-Control-Allow-Origin 用于设置允许跨域请求源地址 (预检请求和正式请求在跨域时候都会验证)
    • Access-Control-Allow-Headers 跨域允许携带的特殊头信息字段 (只在预检请求验证)
    • Access-Control-Allow-Methods 跨域允许的请求方法或者说HTTP动词 (只在预检请求验证)
    • Access-Control-Allow-Credentials 是否允许跨域使用cookies,如果要跨域使用cookies,可以添加上此请求响应头,值设为true(设置或者不设置,都不会影响请求发送,只会影响在跨域时候是否要携带cookies,但是如果设置,预检请求和正式请求都需要设置)。不过不建议跨域使用,除非必要,因为有很多方案可以代替。

    跨域请求时会先发送预检请求,浏览器首先会询问服务器,当前网页所在的域名是否在服务器的许可列表中,以及可以使用的请求头和请求方法。若得到肯定的答复,才会发送正式请求Xhr请求,否则报错

    报错情况1

    Access to XMLHttpRequest at ‘http://localhost:9081/api/’ from origin ‘http://localhost:4443’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: No > ‘Access-Control-Allow-Origin’ header is present on the requested resource.

    通过错误信息可以很清晰的定位到错误priflight说明是个预请求,CORS 机制跨域会首先进行 preflight(一个 OPTIONS 请求), 该请求成功后才会发送真正的请求。这一设计旨在确保服务器对 CORS 标准知情,以保护不支持 CORS 的旧服务器

    解决方案:

    server {
        listen       8080;
        server_name  localhost;
        location  / {
            add_header Access-Control-Allow-Origin 'http://localhost:4443';
            proxy_pass  http://localhost:9081;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    报错情况2

    Access to XMLHttpRequest at ‘http://localhost:9081/api/’ from origin ‘http://localhost:4443’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: It does not have HTTP ok status.

    通过报错信息提示可以得知,是跨域浏览器默认行为的预请求(option请求)没有收到ok状态码,此时再修改配置文件,当请求为option请求时候,给浏览器返回一个状态码(一般是204)

    如果想要每次响应信息都携带头字段信息,需要在最后添加always(经我测试,只有Access-Control-Allow-Origin这个头信息需要加always,其他的不加always也会携带回来)

    server {
        listen       8080;
        server_name  localhost;
        location  / {
            add_header Access-Control-Allow-Origin 'http://localhost:4443' always;
            if ($request_method = 'OPTIONS') {
                return 204;
            }
            proxy_pass  http://localhost:9081;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    报错情况3

    Access to XMLHttpRequest at ‘http://localhost:9081/api/’ from origin ‘http://localhost:4443’ has been blocked by CORS policy: Request header field authorization is not allowed by Access-Control-Allow-Headers in preflight response.
    意思就是预请求响应头Access-Control-Allow-Headers中缺少头信息(各种情况会不一样,在发生跨域后,在自定义添加的头信息是不允许的,需要添加到请求响应头Access-Control-Allow-Headers中,以便浏览器知道此头信息的携带是服务器承认合法的)

    server {
        listen       8080;
        server_name  localhost;
        location  / {
            add_header Access-Control-Allow-Origin 'http://localhost:4443' always;
            if ($request_method = 'OPTIONS') {
                add_header Access-Control-Allow-Headers '*'; #为什么写在if里面而不是接着Access-Control-Allow-Origin往下写?因为这里只有预检请求才会检查
                return 204;
            }
            proxy_pass  http://localhost:9081;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    报错情况4
    如果`if ($request_method = ‘OPTIONS’)``中配置了add_header,那么预检请求外部配置均会失效
    官方文档

    There could be several add_header directives. These directives are inherited from the previous level if and only if there are no add_header directives defined on the current level.

    意思就是当前层级无 add_header 指令时,则继承上一层级的add_header。相反的若当前层级有了add_header,就应该无法继承上一层的add_header。

    server {
        listen       8080;
        server_name  localhost;
        location  / {
            add_header Access-Control-Allow-Origin 'http://localhost:4443' always;
            if ($request_method = 'OPTIONS') {
                add_header Access-Control-Allow-Origin 'http://localhost:4443';
                add_header Access-Control-Allow-Headers '*'; #为什么写在if里面而不是接着Access-Control-Allow-Origin往下写?因为这里只有预检请求才会检查
                return 204;
            }
            proxy_pass  http://localhost:9081;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    但是由于此写法携带上两个 Access-Control-Allow-Origin ,这种情况也是不允许的
    因此修正过的配置如下(其中*可以根据自己的需求替换

    server {
        listen       8080;
        server_name  localhost;
        location  / {
            if ($request_method = 'OPTIONS') {
                add_header Access-Control-Allow-Origin 'http://localhost:4443';
                add_header Access-Control-Allow-Headers '*'; #为什么写在if里面?因为这里只有预检请求才会检查
                add_header Access-Control-Allow-Methods '*';
                add_header Access-Control-Allow-Credentials 'true';
                return 204;
            }
            if ($request_method != 'OPTIONS') {
                add_header Access-Control-Allow-Origin 'http://localhost:4443' always;
                add_header Access-Control-Allow-Credentials 'true';
            }
            proxy_pass  http://localhost:9081;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    或者

    server {
        listen       8080;
        server_name  localhost;
        location  / {
            add_header Access-Control-Allow-Origin 'http://localhost:4443' always;
            add_header Access-Control-Allow-Headers '*';
            add_header Access-Control-Allow-Methods '*';
            add_header Access-Control-Allow-Credentials 'true';
            if ($request_method = 'OPTIONS') {
                return 204;
            }
            proxy_pass  http://localhost:9081;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    参考文章:Nginx 轻松解决跨域问题

  • 相关阅读:
    python-测试代码
    万字长文:FineBI面试题及参考答案详解
    2023年09月 C/C++(五级)真题解析#中国电子学会#全国青少年软件编程等级考试
    CRM系统可以给销售人员带来什么?
    心理咨询预约微信小程序开发制作步骤
    滤波电阻器:用于能源系统和工业的高精度解决方案(1)?
    MySQL事务
    【C++高阶】3.2 vector容器
    学习嵌入式系统的推荐步骤:
    【C++详解】——模板初阶
  • 原文地址:https://blog.csdn.net/CrazyQiQi/article/details/126137047