我有一个网络应用程序,使用 Angular 作为客户端,使用 springboot 作为微服务,使用 mysql 作为数据库。几天前,我向网站添加了一个域,今天我使用 Lets Encrypt 来创建 SSL 证书。
该项目正在使用 docker compose 在 ubuntu 虚拟机上运行
reverse-proxy
以下域的文件。
server {
server_name full_domain_name;
location / {
proxy_pass http://local_ip:4200/ ;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
listen 443 ssl; # managed by Certbot
ssl_certificate
/etc/letsencrypt/live/full_domain_name/fullchain.pem; # managed by
Certbot
ssl_certificate_key
/etc/letsencrypt/live/full_domain_name/privkey.pem; # managed by
Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by
Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
# Redirect HTTP to HTTPS
server {
if ($host = full_domain_name) {
return 301 https://$host$request_uri;
}
listen 80; # HTTP
server_name full_domain_name;
return 404; # Managed by Certbot
}
问题是升级到 https 后,api 调用停止工作。 客户端控制台错误:
net::ERR_SSL_PROTOCOL_ERROR
error in microservice: 2024-11-23T20:06:54.862Z INFO 1 --- \[event\] \[nio-8081-exec-1\] o.apache.coyote.http11.Http11Processor : Error parsing HTTP request header
Note: further occurrences of HTTP request parsing errors will be logged at DEBUG level.
java.lang.IllegalArgumentException: Invalid character found in method name \[(characters)\]. HTTP method names must be tokens
我尝试更新 api 调用以使用 http 代替,(当然)它不起作用:
Mixed Content: The page at 'https://full_domain_name/' was loaded over HTTPS, but requested an insecure resource 'http://full_domain_name:8081/api/endpoint'. This request has been blocked; the content must be served over HTTPS.
我还尝试将 nginx 作为 docker compose 中的单独服务,并在项目中指定
nginx.conf
文件,但这只是让一切变得过于复杂
如果有人偶然发现这篇文章有同样的问题,这就是我所做的:API 调用方法必须更改为类似 https://full_domain_name/service_name
其中“service_name”将用于将请求重定向到在虚拟机内部运行的应用程序
反向代理配置文件如下:
server {
listen 443 ssl;
server_name full_domain_name;
ssl_certificate /etc/letsencrypt/live/full_domain_name/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/full_domain_name/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
proxy_pass http://localhost:4200/; # Points directly to the Angular app running on the VM
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
location /security/ {
proxy_pass http://localhost:8080/; # Internal route for SECURITY microservice
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
location /api/event/ {
proxy_pass http://localhost:8081/api/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
location /api/main/ {
proxy_pass http://localhost:8082/api/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
# Redirect HTTP to HTTPS
server {
if ($host = full_domain_name) {
return 301 https://$host$request_uri;
}
listen 80; # HTTP
server_name full_domain_name;
return 404; # Managed by Certbot
}
例如,/api/event 基于我之前提到的“service_name”。
就我而言,如果客户提出请求
https://full_domain_name/api/event/getAll
nginx 反向代理会将此请求转发到
http://localhost:8081/api/getAll
基本上,请求仍然安全地完成,但 nginx 处理该安全性,而不必配置每个应用程序来执行此操作