Express / Cors / Apache2 Proxy / Angular-为什么响应ACAO标头与某些请求的原始请求来源不匹配?

时间:2020-11-04 15:35:50

标签: angular apache express cors

简短版本:

我的API允许我的前端应用程序通过RegExp原始CORS访问它。我的前端应用程序有两个URL,即服务器名example.org和别名www.example.org。 (这些可以通过Apache2代理访问,请参阅下面的conf,以了解详细版本) 访问别名url时,部分(并非全部)请求失败,因为响应标头ACAO设置为服务器名称。

此行为是随机的,仅影响别名。

这不是不允许或不设置来源的问题,这里的问题是,即使允许两者,请求来源标头和响应Access-Control-Allow-Origin标头也不匹配。

我想了解造成此问题的原因以及如何解决?我不想通过将别名流量重定向到主服务器名称来绕过它。

详细版本:

我的应用程序是一个MEAN堆栈,由以下内容组成:

  1. 在Node / ExpressJS上运行的API带有Apache2反向代理,可通过api.example.org访问。 Express使用CORS软件包,并允许与正则表达式\https?:\/\/(www\.)?(domain\.com)\匹配的原点。

  2. 使用ExpressJS(SSR)提供服务的前端Angular,并且还可以通过Apache2反向代理进行访问。 可以使用example.orgwww.example.org来访问它。

如果不涉及ServerAliases,则整个过程都将被docker化并且可以正常工作,它可以完美地处理没有别名的代理,例如:/https?:\/\/(test\.example\.org)/可以正常工作。

我完全知道,我可以将www.example.org重定向到我的Apache代理中的example.org。 现在,这个问题更多地是关于理解原因并按原样解决问题,而不是绕开它。

直接通过example.org访问并进行Ctrl + Shift + R重载时,一切正常。

通过www.example.org访问并进行Ctrl + Shift + R重载时:

  • 某些请求按预期进行,并且CORS标头设置正确。
  • 但是,某些请求失败,并且原因很简单,对于这些请求,Access-Control-Allow-Origin标头设置为example.org而不是www.example.org。请求中的来源与响应之间不匹配。

因此导致错误:

Access to XMLHttpRequest at 'https://api.example.org/resume' from origin 'https://www.example.org'
has been blocked by CORS policy: 
The 'Access-Control-Allow-Origin' header has a value 'https://example.org' 
that is not equal to the supplied origin.

请求标头:

GET /skill HTTP/1.1
Host: api.example.org
Connection: keep-alive
Accept: application/json, text/plain, */*
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36
Origin: https://www.example.org
Sec-Fetch-Site: same-site
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://www.example.org/
Accept-Encoding: gzip, deflate, br
Accept-Language: fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7
If-None-Match: W/"a842-E9TpqbNXZN+BdTdhAMFBa3wtUgs"

响应头:

HTTP/1.1 200 OK
Date: Wed, 04 Nov 2020 15:24:00 GMT
Server: Apache/2.4.38 (Debian)
Vary: Origin
X-Powered-By: Express
Access-Control-Allow-Origin: https://example.org
Content-Type: application/json; charset=utf-8
ETag: W/"a842-E9TpqbNXZN+BdTdhAMFBa3wtUgs"
Content-Encoding: gzip
Via: 1.1 api.example.org

这可能是由Apache2代理配置错误引起的吗?

我尝试解决的问题:

  • 从Api和前端删除压缩
  • 从角度应用程序中删除缓存拦截器
  • 在我的Vhost上删除ProxyVia和ProxyPreserveHost

这是Express上的cors配置

// Cors initialization :           
private CorsInitialize(): void {
    const corsOptions = {
      origin: /https?:\/\/(www\.)?(example\.org)/
    };
    console.log('Initializing app with cors : ', corsOptions);
    this.expressApp.use(cors(corsOptions));
}

这是我的Apache 2代理conf:

FRONT

<VirtualHost *:80>
    ServerAdmin development@example.org
    ServerName example.org
    ServerAlias www.example.org
    ProxyPreserveHost On
    ProxyVia On
    ProxyPass / http://localhost:3005/ Keepalive=On
    ProxyPassReverse / http://localhost:3005/
    RewriteEngine on
    RewriteCond %{SERVER_NAME} =example.org [OR] RewriteCond %{SERVER_NAME} =www.example.org
    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
<IfModule mod_ssl.c>
    <VirtualHost *:443>
        ServerAdmin development@example.org
        ServerName example.org
        ServerAlias www.example.org
        ProxyPreserveHost On
        ProxyVia On
        ProxyPass / http://localhost:3005/ Keepalive=On
        ProxyPassReverse / http://localhost:3005/

        Include /etc/letsencrypt/options-ssl-apache.conf
        SSLCertificateFile /etc/letsencrypt/live/www.example.org/fullchain.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/www.example.org/privkey.pem
    </VirtualHost>
</IfModule>

API

<VirtualHost *:80>
    ServerAdmin development@example.org
    ServerName api.example.org
    ProxyPreserveHost On
    ProxyVia On
    ProxyPass / http://localhost:3004/ Keepalive=On
    ProxyPassReverse / http://localhost:3004/
    RewriteEngine on
    RewriteCond %{SERVER_NAME} =api.example.org
    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
<IfModule mod_ssl.c>
    <VirtualHost *:443>
        ServerAdmin development@example.org
        ServerName api.example.org
        ProxyPreserveHost On
        ProxyVia On
        ProxyPass / http://localhost:3004/ Keepalive=On
        ProxyPassReverse / http://localhost:3004/

        Include /etc/letsencrypt/options-ssl-apache.conf
        SSLCertificateFile /etc/letsencrypt/live/www.example.org/fullchain.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/www.example.org/privkey.pem
    </VirtualHost>
</IfModule>

这里的问题是,为什么会这样?那是什么原因造成的?

0 个答案:

没有答案