我的API允许我的前端应用程序通过RegExp原始CORS访问它。我的前端应用程序有两个URL,即服务器名example.org
和别名www.example.org
。 (这些可以通过Apache2代理访问,请参阅下面的conf,以了解详细版本)
访问别名url时,部分(并非全部)请求失败,因为响应标头ACAO设置为服务器名称。
此行为是随机的,仅影响别名。
这不是不允许或不设置来源的问题,这里的问题是,即使允许两者,请求来源标头和响应Access-Control-Allow-Origin标头也不匹配。
我想了解造成此问题的原因以及如何解决?我不想通过将别名流量重定向到主服务器名称来绕过它。
我的应用程序是一个MEAN堆栈,由以下内容组成:
在Node / ExpressJS上运行的API带有Apache2反向代理,可通过api.example.org
访问。 Express使用CORS软件包,并允许与正则表达式\https?:\/\/(www\.)?(domain\.com)\
匹配的原点。
使用ExpressJS(SSR)提供服务的前端Angular,并且还可以通过Apache2反向代理进行访问。
可以使用example.org
或www.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
重载时:
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代理配置错误引起的吗?
我尝试解决的问题:
这是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>
这里的问题是,为什么会这样?那是什么原因造成的?