AJAX CORS http 请求 nginx 拒绝

Posted

技术标签:

【中文标题】AJAX CORS http 请求 nginx 拒绝【英文标题】:AJAX CORS http request nginx rejection 【发布时间】:2019-01-18 09:52:48 【问题描述】:

我已经搜索了所有其他相关主题,但找不到针对我的具体问题的解决方案。

我编写了一个包含 AJAX http 请求(get 和 put)的网站。获取这些请求的服务器是 nginx 并在 debian 下运行。

只要我建议我的浏览器忽略 Allow-Access-Header 拒绝,一切都会完美运行。但是如果我不让浏览器忽略它。发生这种情况:

Failed to load http://***/api/devices/7: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://***' is therefore not allowed access.

这是我的 nginx 配置文件,它在 z-wave 基站上运行,所以所有其他配置都与此相关:

worker_processes 1;

error_log /dev/null;

events 
    worker_connections  1024;


http 
    include mime.types;
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    types_hash_max_size 2048;
    keepalive_timeout  65;

client_max_body_size 300M;

    access_log /dev/null;

    upstream hcserver 
        server 127.0.0.1:11111;
        keepalive 15;
    


    server 
        listen 80;
        server_name localhost;

        proxy_read_timeout 400;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;


        location /api/service/ 
            rewrite ^/api/service/(.*) /services/system/$1.php;
        

        location /api/service/backups/ 
            rewrite ^/api/service/backups/(.*)$ /services/system/backups.php?id=$1;
        

        location /api/ 
            proxy_pass http://hcserver;
            proxy_http_version 1.0;
            proxy_set_header Connection "Keep-Alive";
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_buffering off;

            error_page 502 =503 /vendor/en/home/503.html;
        

        location / 
            root   /var/www/;
            index  index.html index.htm index.php;

if ($request_method = 'OPTIONS') 
                add_header 'Access-Control-Allow-Origin' '*';
                add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
                #
                # Custom headers and headers various browsers *should* be OK with but aren't
                #
                #
                add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
                #
                # Tell client that this pre-flight info is valid for 20 days
                #
                add_header 'Access-Control-Max-Age' 1728000;
                add_header 'Content-Type' 'text/plain; charset=utf-8';
                add_header 'Content-Length' 0;
                return 204;
             
             if ($request_method = 'POST') 
                add_header 'Access-Control-Allow-Origin' '*';
                add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
                add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
                add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
             
             if ($request_method = 'GET') 
                add_header 'Access-Control-Allow-Origin' '*';
                add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
                add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
                add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
             

            location ~* \.(css|js|html)$ 
                add_header Cache-Control "must-revalidate, max-age=0, max-age:0, no-cache, no-store";
                add_header Pragma no-cache;
                add_header Expires 'Fri, 01 Jan 2010 00:00:00 GMT';
            

            ssi on;
            ssi_value_length 2056;

            error_page  404              /vendor/404.html;
        

        location ~* \.sh$ 
            proxy_pass   http://127.0.0.1:8000;
        

        location ~* \.php$ 
            proxy_pass   http://127.0.0.1:8000;
        

        location ~* \.php\?.* 
            proxy_pass   http://127.0.0.1:8000;
        

        rewrite ^/vendor/icons/User(.*) /vendor/icons/userIcons/User$1;
        rewrite ^/vendor/icons/rooms/User(.*) /vendor/icons/rooms/userIcons/User$1;
        rewrite ^/vendor/icons/scena/User(.*) /vendor/icons/scena/userIcons/User$1;
        rewrite ^/vendor/n_vicons/User(.*) /vendor/n_vicons/userIcons/User$1;
        rewrite ^/vendor/data_request(.*)php(.*) /api/mobile$2;
        rewrite ^/vendor/(js/)(.*) /vendor/js/$2 last;
        rewrite ^/vendor/([a-z][a-z]/)(.*) /vendor/$2;
    

亲切的问候,请不要破解我的IP:127.0.0.1 ;)

【问题讨论】:

【参考方案1】:

您的配置中的缩进有点偏离,但在我看来,您只是在 location / 块内添加了 CORS 标头。作为起点,尝试将这些标头提升到 server 块,如下所示:

server 
    listen 80;
    server_name localhost;

    add_header Access-Control-Allow-Origin $http_origin;
    add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
    add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range";
    add_header Access-Control-Expose-Headers "Content-Length,Content-Range";
    add_header Access-Control-Max-Age 1728000;

现在,这些规则将应用于此服务器的每个位置块(以及每个$request_method)。

如果您需要特定于上下文的规则 - 例如,不同端点的不同 CORS 标头值 - 这仍然是一个很好的起点,因为它将验证包罗万象的解决方案。一旦您某些东西工作了,就可以更轻松地对规则进行小幅更改,同时进行测试以找出问题所在。

希望这会有所帮助。如果没有,更新您的问题,包括完整的curl - 请求和响应的标头和正文 - 将非常有帮助。

【讨论】:

你是绝对正确的。我不知道,因为我以前从未配置过 nginx,现在感觉很愚蠢。还有另一个问题,因为我发送了 Access-Control-Allow-Origin '*' 不允许的 Authorization 标头 ... 很高兴为您提供帮助!起初它令人困惑,但很快就会成为第二天性。我很高兴您提到了授权:如果您要对用户进行认证(例如,通过设置 cookie),您还需要传递 Access-Control-Allow-Credentials 标头。该行应如下所示:add_header Access-Control-Allow-Credentials "true";。 (你说得对,通配符在这种情况下不起作用。)

以上是关于AJAX CORS http 请求 nginx 拒绝的主要内容,如果未能解决你的问题,请参考以下文章

jQuery ajax CORS 请求

CORS 跨域 实现思路及相关解决方案

使用 ajax 发出 http 请求以获得基本授权和 cors

nginx ssl 拒绝不匹配的 server_name 请求

使用 JAX-RS/RESTEasy 实现 CORS 的 Ajax 请求

Cors 阻止 Nginx 上状态为 403 的请求