![使用 Nginx 的 Angular CORS](https://linux22.com/image/759531/%E4%BD%BF%E7%94%A8%20Nginx%20%E7%9A%84%20Angular%20CORS.png)
网上针对同一主题提出了几个问题,但都没有任何效果。
我有一个 serverXYZ,运行着一个 Angular 应用程序、一个用于身份验证的后端 tomcat web 应用程序和一个 nginx 服务器。Angular 应用程序在端口 4200 上,tomcat 应用程序在端口 8080 上。所有内容都在同一台主机上。
角度应用程序有一个 environment.ts 文件(注释的字符串是我的测试之一,请参阅下面的 nginx conf):
export const environment = {
production: false,
// apiUrl: 'http://serverXYZ:444/api'
apiUrl: 'http://localhost:8080/backend'
};
nginx 配置:
server {
listen 444;
server_name serverXYZ;
location / {
proxy_pass http://localhost:4200;
//websocket
proxy_set_header HOST $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass_request_headers on;
proxy_http_version 1.0;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_read_timeout 120s;
if ($request_method = 'OPTIONS') {
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-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 /api {
proxy_pass http://localhost:8080/backend;
if ($request_method = 'OPTIONS') {
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-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';
}
}
}
后端 tomcat 应用程序在其 web.xml 中有以下内容:
...
<!-- Tomcat built in CORS implementation -->
<!-- https://tomcat.apache.org/tomcat-7.0-doc/config/filter.html -->
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
<init-param>
<param-name>cors.allowed.headers</param-name>
<param-value>Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.methods</param-name>
<param-value>GET,POST,HEAD,OPTIONS,PUT,DELETE</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- End of built in CORS implementation -->
...
我使用我的电脑,打开浏览器,使用所述配置,如果我连接到 http://serverXYZ:444,应用程序就会显示出来,但我在身份验证时收到 CORS 错误(CORS 请求失败)。如果我使用 environment.ts 中注释字符串的配置,浏览器身份验证不会显示 CORS,只会显示 403。当然,身份验证 API 已经过测试并正常运行。
我完全不知道,出了什么问题?另外,使用 nginx 解决这个问题是我的首选方法,但不是强制性的。
编辑: 我再补充一条信息,我使用“ng serve --disableHostCheck=true”启动了 angular 应用程序。我不知道在这种情况下是否应该使用“--publicHost”选项或“--host 0.0.0.0”?
编辑2: 我刚刚看到的另一件事是,Firefox 在 OPTIONS 请求上没有给我任何错误,只有在 POST 上才出现 Cors。
答案1
你看过著名的如果是邪恶的文章?文章指出
在位置上下文中可以完成的唯一 100% 安全的事情是:
return ...; rewrite ... last;
在大多数情况下,这些说明过于严格,通常你可以安全地使用来自ngx_http_rewrite_module
在if
块内。但是使用包括该指令在内的任何其他指令add_header
都非常不安全,并且可能导致不可预测的结果。下面是我编写此类配置的方法:
map $request_method $route {
GET main;
POST main;
OPTIONS options;
default invalid;
}
map $request_method $api {
GET api;
POST api;
OPTIONS options;
default invalid;
}
server {
listen 444;
server_name serverXYZ;
location / {
try_files /dev/null @$route;
}
location /api {
try_files /dev/null @$api;
}
location @main {
# websocket conntection setup
proxy_set_header HOST $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass_request_headers on;
proxy_http_version 1.0;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_read_timeout 120s;
# pass the request
proxy_pass http://localhost:4200;
# add response CORS headers
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 @api {
# transform the URI
rewrite ^/api(.*) /backend$1 break;
# pass the request
proxy_pass http://localhost:8080;
# add response CORS headers
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 @options {
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-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
location @invalid {
# method not allowed
add_header Allow "GET, POST, OPTIONS";
return 405;
}
}