我正在使用一个启用了csrf的springboot thymeleaf应用程序。为了防止我的应用程序出现XSS漏洞,我按照这个的教程添加了一个过滤器。我把XSSFilter、XSSRequestWrapper和XSSUtils的文件从这里复制过来。可能我在带状功能中唯一添加的新东西就是这段代码。
String returnValue = Jsoup.clean(value, Whitelist.none());
returnValue = Parser.unescapeEntities(returnValue, true);
return returnValue;
我不得不添加这个,因为Jsoup clean在添加amp;来代替&。
我的应用程序有一个登录页面,只有当用户成功通过认证后,才允许他进入。在没有过滤器的情况下,该应用程序工作得非常好。但是,当我添加了过滤器后,应用程序就不能登录,也不会显示任何错误。这是我的index.html,其中thymeleaf插入了csrf令牌。
<html xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head id="Head1" >
<title>Home</title>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252"/>
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE11"/>
<meta name="_csrf" th:content="${_csrf.token}"/>
<meta name="_csrf_header" th:content="${_csrf.headerName}"/>
<link rel="stylesheet" th:href="@{css_page_specific/index.css}">
<link rel="stylesheet" th:href="@{css_general/toggle-button-modern.css}">
<script type="text/javascript" th:src="@{commons.js}"></script>
</head>
<form method="post" id="init-form2" th:action="@{/login}" style="max-width: 350px; margin: 0 auto;">
<div class="form-group">
<input type="text" name="username" id="ad-auth-username" placeholder="id">
</div>
<div class="form-group">
<input type="password" name="password" id="ad-auth-password" placeholder="Password">
</div>
这是我的登录控制器。
@Controller
public class LoginController {
@GetMapping("/login")
public String showLoginForm(Model model) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null || authentication instanceof AnonymousAuthenticationToken) {
return "login";
}
return "redirect:/";
}
@GetMapping("/logout")
public String logoutPage(HttpServletRequest request, HttpServletResponse response) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null){
new SecurityContextLogoutHandler().logout(request, response, auth);
}
return "redirect:/";
}
}
这里是我的网络安全配置。
@Override
protected void configure(HttpSecurity http) throws Exception {
http.requiresChannel().anyRequest().requiresSecure().and().authorizeRequests().antMatchers("/login","/css_general/**","/css_page_specific/**","/**/*.js","/**/*.css")
.permitAll()
.anyRequest()
.authenticated()
.and().formLogin(form -> form
.loginPage("/login")
.defaultSuccessUrl("/index.html")
.failureUrl("/login?error=true")
)
.sessionManagement().invalidSessionUrl("/login")
.and()
.httpBasic()
.and()
.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/login").invalidateHttpSession(true).deleteCookies("JSESSIONID")
.permitAll()
.and()
.cors().disable()
.headers()
.xssProtection()
.and()
.contentSecurityPolicy("script-src 'self'");
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/css_general/**", "/css_page_specific/**","/resources/static/css_general/**","/resources/static/css_page_specific/**","/static/css_page_specific/**","/static/css_general/**");
}
现在在我的过滤器中,如果我不放xss剥离逻辑并放一个断点,我看到它包含3个参数。
username, password and _csrf.
这个过滤链经过,最终允许传递给csrfFilter,而csrfFilter则成功了。我能够成功登录。
但是,如果我输入XSSFilter代码,我没有看到3个参数中的任何一个被传递,最终csrf过滤器失败,我停留在登录页面上,没有任何错误信息。我知道过滤器是为每个请求调用的,但我检查了每个请求,我就是没有看到这些参数被传递,这就是我怀疑csrfFilter失败的原因。
我怎样才能让xss过滤器工作并成功登录?我只在登录页面使用了thymeleaf,其余的页面只是通过常规的json请求和响应与服务器交换数据。
在没有添加XSSFilter的情况下,成功地进行了认证。在过滤器中收到3个参数 - 用户名、密码和_csrf。添加XSSFilter后,无法认证和登录 - 在过滤器中收到0个参数。我怎样才能将传递给应用程序的所有输入限制为有效的、允许列表的内容,并确保服务器发送的所有响应/输出都是HTML/URL/JavaScript编码的,这取决于应用程序使用数据的环境?
StackOverflow:java - SpringBoot with XSSFilter fails to authenticate due to missing CSRF Token - Stack Overflow