Tomcat 8.5.51记录Angular HTTP请求日志及转发客户端IP问题
看起来你遇到了两个关联的问题:Tomcat抓不到Angular的API请求日志,同时后端应用拿到的是Tomcat的IP而非浏览器真实IP。结合你的Tomcat 8.5.51版本和UI→Tomcat主机→应用服务器的架构,我给你针对性的解决方案:
需求1:在Tomcat日志中打印Angular的HTTP请求日志
第一步:先确认Angular请求是否真的经过Tomcat
你现在看到的日志都是静态资源(比如fontawesome的字体文件),很可能你的Angular代码里的API请求直接调用了应用服务器的地址,根本没走Tomcat——那Tomcat自然没法记录这些请求。
解决办法:把Angular的API baseUrl改成Tomcat的地址(比如/api),然后在Tomcat的server.xml里配置转发规则,把/api/*的请求转发到应用服务器。比如用RewriteValve或者ProxyValve都能实现。
第二步:调整AccessLogValve的作用范围
如果你的AccessLogValve是配置在<Host>节点下,它只会记录该Host下的Web应用请求。如果Angular的请求走了其他Context,或者你有多个Host配置,把AccessLogValve移到<Engine>节点下,这样所有Host的请求都会被记录:
<Engine name="Catalina" defaultHost="localhost"> <!-- 把AccessLogValve放在Engine级别,覆盖所有Host --> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log" suffix=".txt" pattern="combined" resolveHosts="false"/> <!-- 你的Host配置 --> <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true"> <Valve className="org.apache.catalina.valves.RemoteIpValve" /> </Host> </Engine>
第三步:修正RequestDumperFilter的日志输出
你加的RequestDumperFilter其实是有用的,但它的日志默认输出在catalina.out里(不是access_log文件),而且默认是DEBUG级别,可能没开启。去Tomcat的conf/logging.properties里加两行:
org.apache.catalina.filters.RequestDumperFilter.level = INFO org.apache.catalina.filters.RequestDumperFilter.handlers = java.util.logging.ConsoleHandler
这样就能在catalina.out里看到所有经过这个过滤器的请求细节,包括Angular的HTTP请求了。
需求2:让Tomcat将浏览器IP作为X-Forwarded-IP转发给应用服务器
你现在的RemoteIpValve配置太简略了,默认它不会自动识别并转发真实IP,得明确告诉它哪些是可信的代理IP,以及从哪个请求头取真实IP。
第一步:完善RemoteIpValve配置
修改server.xml里的RemoteIpValve,根据你的网络环境调整参数:
<Valve className="org.apache.catalina.valves.RemoteIpValve" internalProxies="10\.2\.\d+\.\d+" <!-- 填Tomcat主机服务器的IP段,因为它是转发到应用服务器的可信代理 --> remoteIpHeader="X-Forwarded-For" remoteIpProxiesHeader="X-Forwarded-By" protocolHeader="X-Forwarded-Proto"/>
这里的internalProxies是关键:它指定哪些IP是可信的,Tomcat会忽略这些IP的地址,直接取X-Forwarded-For里的真实客户端IP。
第二步:确保Tomcat转发请求时携带X-Forwarded-For
如果Tomcat是作为反向代理转发请求到应用服务器(比如用ProxyValve),要确保转发时把X-Forwarded-For头传过去。比如配置ProxyValve:
<Valve className="org.apache.catalina.valves.ProxyValve" proxyHost="你的应用服务器IP" proxyPort="应用服务器端口"/>
这个Valve会自动把真实客户端IP放到X-Forwarded-For头里,然后转发给后端应用服务器。
第三步:应用服务器获取真实IP
后端应用服务器可以直接通过request.getHeader("X-Forwarded-For")拿到真实的浏览器IP;如果应用服务器也是Tomcat,你可以在它的server.xml里也配置同样的RemoteIpValve,这样request.getRemoteAddr()就能直接返回真实IP,不用改代码。
几个额外的排查点
- 检查Tomcat日志级别:确保
org.apache.catalina.valves的日志级别是INFO或更低,不然可能看不到日志。 - 排查跨域问题:如果Angular直接访问应用服务器,会触发CORS的OPTIONS请求,这些请求是否被Tomcat记录?如果没记录,可能是CORS配置的问题。
- 自定义AccessLog格式:如果需要更详细的信息,可以修改AccessLogValve的
pattern,比如加上%{X-Forwarded-For}i来直接在access_log里看到真实IP:pattern="%h %l %u %t "%r" %s %b "%{Referer}i" "%{User-Agent}i" "%{X-Forwarded-For}i""
内容的提问来源于stack exchange,提问作者scoder

