java 由https通过Apache反向代理发送到Tomcat的POST请求以https返回状态403

gojuced7  于 12个月前  发布在  Java
关注(0)|答案(1)|浏览(141)

**配置:**不安全的后端(Sringboot 3)部署在Tomcat 10(java 17)服务器上,前端(Angular 15)部署在Apache 2.4 web服务器上。

Web服务器还充当反向代理,以规避跨域资源共享(CORS)的同源安全策略禁止发出Ajax请求。如果没有反向代理,前端将无法访问后端。

**Http:**当浏览器通过http访问前端时,此配置可以正常工作。
**Https:**当浏览器以https访问前端执行JavaScript代码(Angular)时,以及发送和处理Web服务器从'GET'请求返回的响应时,此配置也有效。另一方面,当前端向Web服务器(apache)发送'POST'请求时,Web服务器返回403(禁止)。下面是我们在浏览器(devtools)的“网络”选项卡中看到的内容:

Header :
Request URL:https://letstryfront.com/api/genjournallinespagedmultisort?page=0&size=10
Request Method:POST
Status Code:403 Forbidden
Remote Address:192.168.56.105:443
Referrer Policy:strict-origin-when-cross-origin

Response Header :
Connection:Keep-Alive
Content-Type:text/plain

Date:Fri, 29 Dec 2023 09:29:11 GMT
Keep-Alive:timeout=5, max=100
Server:Apache/2.4.58 (Unix) OpenSSL/3.2.0
Transfer-Encoding:chunked

Accept:application/json, text/plain, */*
Accept-Encoding:gzip, deflate, br
Accept-Language:en-GB,en-US;q=0.9,en;q=0.8
Connection:keep-alive
Content-Length:2
Content-Type:application/json
Host:letstryfront.com
Origin:https://letstryfront.com
Referer:https://letstryfront.com/journal
Sec-Ch-Ua:"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"
Sec-Ch-Ua-Mobile:?0
Sec-Ch-Ua-Platform:"Windows"
Sec-Fetch-Dest:empty
Sec-Fetch-Mode:cors
Sec-Fetch-Site:same-origin
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36

字符串
令人惊讶的是,当使用curl发送“POST”请求时,Web服务器通常会执行200(成功)。

curl -X POST -v "https://letstryfront.com/api/genjournallinespagedmultisort?page=5&size=10" -H "accept: */*" -H "Content-Type: application/json" -d "[ { \"sortField\": \"lineno\", \"sortDirection\": \"asc\", \"orderSeq\": 0 }]" -o journallines.json --ssl-no-revoke


tomcat10日志显示“Completed 200 OK”,但找不到403 Forbidden。
然而,Apache web服务器日志显示,在tomcat上运行的后端返回了403:Status from backend:403,referer:https://letstryfront.com/journal
以下是Apache服务器级别的virtualhost配置:

<VirtualHost *:80>
    ServerName letstryfront.com
    ServerAlias *.letstryfront.com

    SSLProxyEngine on
    SSLProxyCheckPeerCN Off
    SSLProxyCheckPeerName Off
    SSLProxyVerify none

    DocumentRoot "/srv/http/letstryfront"
    <Directory /srv/http/letstryfront>
           Options Indexes FollowSymLinks MultiViews
           Allow from all
           AllowOverride All
           Require all granted
    </Directory>

    <LocationMatch "/api">
      ProxyPreserveHost on
    </LocationMatch>
    ProxyPass /api http://localhost:8080/letstrysome/api
    ProxyPassReverse /api http://localhost:8080/letstrysome/api

    Proxypass /external/geocode/ https://maps.googleapis.com/maps/api/geocode/
    ProxypassReverse /external/geocode/ https://maps.googleapis.com/maps/api/geocode/

    Proxypass /external/v1/ https://api.open-meteo.com/v1/
    ProxypassReverse /external/v1/ https://api.open-meteo.com/v1/

    RewriteEngine On

    RewriteCond %{REQUEST_URI}$1 external/geocode/json
    RewriteCond %{QUERY_STRING} ^(address=.*&)key=.*$
    RewriteRule ^ %{REQUEST_URI}?%1key=REMOVED [NE,PT,END]

    LogLevel trace2
    ErrorLog "/var/log/httpd/letstryfront.com-error_log"
    CustomLog "/var/log/httpd/letstryfront.com-access_log" common

</VirtualHost>

<VirtualHost *:443>
    ServerName letstryfront.com
    ServerAlias 192.168.56.105 *.letstryfront.com

    SSLEngine on
    SSLCertificateFile /etc/ssl/certs/letstryfront.com.crt
    SSLCertificateKeyFile /etc/ssl/private/letstryfront.com.key
    SSLCACertificatePath /etc/ssl/certs/

    SSLProxyEngine on
    SSLProxyCheckPeerCN Off
    SSLProxyCheckPeerName Off
    SSLProxyVerify none

    DocumentRoot "/srv/http/letstryfront"
    <Directory /srv/http/letstryfront>
           Options Indexes FollowSymLinks MultiViews
           Allow from all
           AllowOverride All
           Require all granted
    </Directory>

    <LocationMatch "/api">
      ProxyPreserveHost on
    </LocationMatch>
    ProxyPass /api http://localhost:8080/letstrysome/api
    ProxyPassReverse /api http://localhost:8080/letstrysome/api

    Proxypass /external/geocode/ https://maps.googleapis.com/maps/api/geocode/
    ProxypassReverse /external/geocode/ https://maps.googleapis.com/maps/api/geocode/

    Proxypass /external/v1/ https://api.open-meteo.com/v1/
    ProxypassReverse /external/v1/ https://api.open-meteo.com/v1/

    RewriteEngine On

    RewriteCond %{REQUEST_URI}$1 external/geocode/json
    RewriteCond %{QUERY_STRING} ^(address=.*&)key=.*$
    RewriteRule ^ %{REQUEST_URI}?%1key=REMOVED [NE,PT,END]

    LogLevel trace4
    ErrorLog "/var/log/httpd/letstryfront.com-tls-error_log"
    CustomLog "/var/log/httpd/letstryfront.com-tls-access_log" common

</VirtualHost>


我更改了https virtualhost配置(443)几次。我想可以强制POST请求通过。我仍在测试。另一种解决方案可能是在后端级别进行操作。如果有人有解决方案,无论是在Tomcat 10服务器的后端级别(Springboot 3)还是Apache 2.4配置,我都会感兴趣。

xfb7svmp

xfb7svmp1#

我再次查看了日志,注意到curl发送的头与浏览器发送的头不同。因此我将RequestHeader unset Origin指令添加到https virtualhost配置文件中。现在https virtualhost配置文件如下所示:

<VirtualHost *:443>
  ServerName letstryfront.com
  ServerAlias 192.168.56.105 *.letstryfront.com

  SSLEngine on
  SSLCertificateFile /etc/ssl/certs/letstryfront.com.crt
  SSLCertificateKeyFile /etc/ssl/private/letstryfront.com.key
  SSLCACertificatePath /etc/ssl/certs/

  SSLProxyEngine on
  SSLProxyCheckPeerCN Off
  SSLProxyCheckPeerName Off
  SSLProxyVerify none

  RequestHeader unset Origin
  ...  
</VirtualHost>

字符串
在这个改变之后,我重新启动了httpd服务,现在它很好。虽然这个解决方案工作,我想知道是否有另一种方法来解决这个问题,在后台级别。

相关问题