You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

集成OWASP CSRF Guard后出现空白页及无响应问题排查

集成OWASP CSRF Guard后页面加载异常排查与修复

问题背景

基于Java 17、Tomcat 10.1.25的Web应用,替换ESAPI为OWASP Java HTML Sanitizer+CSRF Guard,前者集成正常,后者出现以下异常:

  • 服务器启动正常(可见CSRF Guard配置日志)
  • 页面可打开,但静态资源(图片、CSS等)无法加载
  • 登录时Login Servlet初始化,但doPost()未执行,跳转空白页
  • 偶发性启动后直接显示空白页,日志/控制台无报错,所有响应码200但内容为空

配置文件

web.xml

<context-param>
  <param-name>Owasp.CsrfGuard.Config</param-name>
  <param-value>WEB-INF/csrfguard.properties</param-value>
</context-param>

<listener>
  <listener-class>org.owasp.csrfguard.CsrfGuardServletContextListener</listener-class>
</listener>

<listener>
  <listener-class>org.owasp.csrfguard.CsrfGuardHttpSessionListener</listener-class>
</listener>

<filter>
  <filter-name>AccessFilter</filter-name>
  <filter-class>wy.web.app.security.AccessFilter</filter-class>
</filter>
<filter-mapping>
  <filter-name>AccessFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

<filter>
  <filter-name>CSRFGuard</filter-name>
  <filter-class>org.owasp.csrfguard.CsrfGuardFilter</filter-class>
</filter>
<filter-mapping>
  <filter-name>CSRFGuard</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

<servlet>
  <servlet-name>JavaScriptServlet</servlet-name>
  <servlet-class>org.owasp.csrfguard.servlet.JavaScriptServlet</servlet-class>
</servlet>

<servlet-mapping>
  <servlet-name>JavaScriptServlet</servlet-name>
  <url-pattern>/JavaScriptServlet</url-pattern>
</servlet-mapping>

<session-config>
  <session-timeout>30</session-timeout>
</session-config>
<welcome-file-list>
  <welcome-file>login.jsp</welcome-file>
</welcome-file-list>

csrfguard.properties

org.owasp.csrfguard.configuration.provider.factory = org.owasp.csrfguard.config.PropertiesConfigurationProviderFactory
org.owasp.csrfguard.Enabled = true

# 已测试true和false两种取值
org.owasp.csrfguard.ValidateWhenNoSessionExists = true

org.owasp.csrfguard.TokenLength = 32
org.owasp.csrfguard.TokenName = OWASP-CSRFTOKEN
org.owasp.csrfguard.SessionKey = OWASP-CSRFTOKEN
org.owasp.csrfguard.PRNG = SHA1PRNG
org.owasp.csrfguard.PRNG.Provider = SUN

org.owasp.csrfguard.Ajax = true

org.owasp.csrfguard.LogicalSessionExtractor = org.owasp.csrfguard.session.SessionTokenKeyExtractor

org.owasp.csrfguard.JavascriptServlet.sourceFile = WEB-INF/Owasp.CsrfGuard.js
org.owasp.csrfguard.JavascriptServlet.domainStrict = false
org.owasp.csrfguard.JavascriptServlet.cacheControl = private, maxage=28800, no-cache, no-store, must-revalidate
org.owasp.csrfguard.JavascriptServlet.refererPattern = .*
# 已测试true和false两种取值
org.owasp.csrfguard.JavascriptServlet.refererMatchProtocol = false
# 已测试true和false两种取值
org.owasp.csrfguard.JavascriptServlet.refererMatchDomain = false
org.owasp.csrfguard.JavascriptServlet.injectIntoForms = true
org.owasp.csrfguard.JavascriptServlet.injectGetForms = true
org.owasp.csrfguard.JavascriptServlet.injectFormAttributes = true
org.owasp.csrfguard.JavascriptServlet.injectIntoAttributes = true
org.owasp.csrfguard.JavascriptServlet.injectIntoDynamicNodes = false
org.owasp.csrfguard.JavascriptServlet.xRequestedWith = OWASP CSRFGuard Project
org.owasp.csrfguard.JavascriptServlet.UnprotectedExtensions = js, css, gif, png, ico, jpg

org.owasp.csrfguard.configOverlay.hierarchy = file:WEB-INF/csrfguard.properties

# 将登录页标记为未受保护,至少用于测试
org.owasp.csrfguard.unprotected.Login = %servletContext%/login.jsp
org.owasp.csrfguard.unprotected.Error = %servletContext%/error.jsp

# 检测到攻击时执行的操作
# 1. 记录信息
org.owasp.csrfguard.action.Log = org.owasp.csrfguard.action.Log
org.owasp.csrfguard.action.Log.Message = Potential cross-site request forgery (CSRF) attack thwarted (user:%user%, ip:%remote_ip%, method:%request_method%, uri:%request_uri%, error:%exception_message%)
# 2. 轮换令牌;AJAX不支持此操作
#org.owasp.csrfguard.action.Rotate = org.owasp.csrfguard.action.Rotate
# 3. 使被滥用的令牌失效
#org.owasp.csrfguard.action.Invalidate=org.owasp.csrfguard.action.Invalidate
# 4. 将用户/攻击者重定向到指定页面
#org.owasp.csrfguard.action.Redirect = org.owasp.csrfguard.action.Redirect
#org.owasp.csrfguard.action.Redirect.Page = /Owasp.CsrfGuard.Test/error.html
org.owasp.csrfguard.Logger = org.owasp.csrfguard.log.JavaLogger
org.owasp.csrfguard.log.JavaLogger.level = TRACE
org.owasp.csrfguard.Config.Print = true
org.owasp.csrfguard.forceSynchronousAjax = true

排查与修复方案

1. 调整过滤器执行顺序

当前AccessFilter在CSRFGuardFilter之前执行,可能导致CSRF Guard的响应处理逻辑被拦截或截断。修改web.xml,将CSRFGuardFilter放在AccessFilter之前:

<!-- 先加载CSRFGuardFilter -->
<filter>
  <filter-name>CSRFGuard</filter-name>
  <filter-class>org.owasp.csrfguard.CsrfGuardFilter</filter-class>
</filter>
<filter-mapping>
  <filter-name>CSRFGuard</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

<!-- 后加载自定义AccessFilter -->
<filter>
  <filter-name>AccessFilter</filter-name>
  <filter-class>wy.web.app.security.AccessFilter</filter-class>
</filter>
<filter-mapping>
  <filter-name>AccessFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

2. 全局排除静态资源保护

JavascriptServlet.UnprotectedExtensions仅针对JS Servlet的资源,需在csrfguard.properties中添加全局未保护规则,让静态资源跳过CSRF校验:

# 按后缀排除静态资源
org.owasp.csrfguard.unprotected.StaticFiles = %servletContext%/*.js, %servletContext%/*.css, %servletContext%/*.gif, %servletContext%/*.png, %servletContext%/*.ico, %servletContext%/*.jpg
# 若静态资源存放在指定目录(如/static/),添加目录排除规则
org.owasp.csrfguard.unprotected.StaticDir = %servletContext%/static/*

3. 关闭无Session时的校验

当ValidateWhenNoSessionExists=true时,未登录状态(无Session)的请求会被强制校验,即使登录页标记为未保护,也可能存在规则匹配异常。暂时设置为false测试:

org.owasp.csrfguard.ValidateWhenNoSessionExists = false

4. 修正JS资源加载路径

若使用CSRF Guard自带的Owasp.CsrfGuard.js,无需手动放置在WEB-INF,改为从类路径加载(依赖包已包含):

org.owasp.csrfguard.JavascriptServlet.sourceFile = classpath:Owasp.CsrfGuard.js

5. 排查响应截断问题

检查Tomcat的localhost.log或应用日志(已开启TRACE级别),查看CSRF Guard是否有拦截记录。同时检查自定义AccessFilter是否存在修改响应输出流、提前关闭流的逻辑,导致响应内容无法正常输出。

6. 确认版本兼容性

Tomcat 10.1基于Jakarta EE 9.1规范,需使用CSRF Guard 4.0及以上版本(旧版本仅支持Java EE,存在Servlet API兼容问题)。


内容的提问来源于stack exchange,提问作者Izek H

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 21:05:54