带有 auth_request_module 的 Nginx 反向代理应用程序抛出 CORS 错误

Nginx with auth_request_module to reverse proxied app throws CORS errors

我正在开发一个 nginx 服务器,仅当用户通过身份验证时才用作本地 webapp 的反向代理。 这是我的 nginx myconfiguration.conf 飞入 etc/nginx/sites-enabled/:

# Proxy Server to back-end site
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name internal.example.com;

        
    # Internal web application 
    location / {
       auth_request /aut;
       error_page 401 = @error401;
       proxy_pass http://192.168.1.13:8080;
    }
    
    # Autentication application
    location = /aut {
       proxy_pass_request_body off;
       proxy_set_header Content-Length "";
       proxy_pass http://192.168.1.130:8080/Autentication/Auth;
    }

    # Redirect to login site 
    location @error401 {
       return 302 http://example.com/Autentication/login;
    }
     
}

# Proxy server to Login site
server {
    listen 80;
    listen [::]:80;
    server_name example.com;
    
    # Internal web application for login
    location / {
        proxy_pass http://192.168.1.130:8080;
    }
}

如果用户请求通过 auth_request /aut; 进行身份验证,一切都很好,但如果我们强制 auth_request(在我们的身份验证 api 上)回答 'HTTP error 401',我们就会滑倒分为两种不同的情况:

A)如果用户刷新页面,一切正常:这意味着请求没有通过授权,客户端被重定向到我们的登录页面http://example.com/Autentication/login

B) 如果用户尝试使用 javascript 从 api 获取数据,我们会在浏览器控制台中收到这 3 个错误:

ERROR .1)
Access to XMLHttpRequest at 'http://example.com/Autentication' 
(redirected from 'http://internal.example.com/TestServer/servlet') 
from origin 'http://internal.example.com' has been blocked by CORS policy: 
Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response

ERROR 2)
Access to XMLHttpRequest at 'http://example.com/Autentication' 
(redirected from 'http://internal.example.com/page.html') 
from origin 'http://internal.example.com/' has been blocked by CORS policy: 
No 'Access-Control-Allow-Origin' header is present on the requested resource.

ERROR 3)
Access to XMLHttpRequest at 'http://example.com/Autentication' 
(redirected from 'http://internal.example.com/TestServer/servlets) 
from origin 'http://internal.example.com' has been blocked by CORS policy: 
Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.

我们按照建议 here 尝试在 location 块内的 nginx myconfiguration.conf 中添加此配置,但它没有解决我们的问题:

if ($request_method = 'OPTIONS') {
     add_header 'Access-Control-Allow-Origin' '*' always;
     add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
     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' '*' always;
     add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
     add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
     add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
}
if ($request_method = 'GET') {
     add_header 'Access-Control-Allow-Origin' '*' always;
     add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
     add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
     add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
}

经过几天的测试,我解决了这个问题: tomcat 服务器上不需要配置(我的意思是 tomcat 服务器上没有处理任何 cors headers)。 我更改并足以让整个基础架构正常工作的是 NGINX 上的 myconfig.conf 文件。

这是正确的myconfig.conf

# SERVER PROXY INTERNAL (can access only when auth_request is passed)----------------------------------------
server {
       listen 80 default_server;
       listen [::]:80 default_server;
       server_name internal.example.com;



    # Proxy to internal tomcat with auth_request to /provaut
        location / {
          auth_request /prova_aut;
          error_page 401 = @error401;
          proxy_pass http://192.168.1.13:8080;
        }

        location = /prova_aut {
           proxy_pass_request_body off;
           proxy_set_header Content-Length "";
           proxy_pass http://192.168.1.130:8080/Auth;
        }

    # Redirect to LOGIN 
        location @error401 {
           return 302 http://example.com/Login;
      }  
}


#  SERVER PROXY FOR LOGIN AND AUTH TOMCAT'S APP --------------------------
server {
       listen 80;
       listen [::]:80;
       server_name example.com;



        access_log /var/log/nginx/reverse-access.log;
        error_log /var/log/nginx/reverse-error.log;

    # Proxy to Authentication_app's tomcat  
        location / {
           if ($request_method = 'OPTIONS') {
                add_header 'Access-Control-Allow-Origin' 'http://internal.example.com' always;
                add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
                add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
                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' 'http://internal.example.com' always;
                add_header 'Access-Control-Allow-Credentials' 'true' always;
                add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
                add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
                add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range,Access-Control-Allow-Origin,Access-Control-Allow-Credentials' always;
           }
           if ($request_method = 'GET') {
                add_header 'Access-Control-Allow-Origin' 'http://internal.example.com' always;
                add_header 'Access-Control-Allow-Credentials' 'true' always;
                add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
                add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
                add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range,Access-Control-Allow-Origin,Access-Control-Allow-Credentials' always;
           }
           proxy_pass http://192.168.1.130:8080;
         }
}

真正成功的是在 Login/Auth 服务器的 /location 块中添加以下两行 'Access-Control-Allow-Origin' 'http://internal.example.com' always;'Access-Control-Allow-Credentials' 'true' always;

我真的希望这可以帮助其他人 ;)