在Spring Security 5.1.4中使用CSRF保护时遇到问题。
我已经为应用程序设置了自定义登录页面。当用户输入他或她的凭据时,将发出AJAX请求。成功处理程序执行其职责,并在响应中返回JSON文档。 AJAX调用成功后,通过删除用户名和密码字段并将其替换为下拉字段和“继续”按钮来动态更新屏幕。
当用户从下拉列表中进行选择并单击“继续”按钮时,将更改表单上的操作,并使用POST方法提交表单。然后将用户定向到主屏幕。不幸的是,应用程序以禁止(403)错误作为响应。
当我修改WebSecurityConfigurerAdapter以禁用CSRF保护时,我的登录屏幕将按预期运行。
提交表单时,我是否缺少某些内容?请注意,我在表单元素内的隐藏字段中包含了CSRF参数和令牌。
WebSecurityConfigurerAdapter
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/css/**", "/images/**", "/js/**")
.permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.successHandler(customAuthenticationHandler)
.permitAll()
.and()
.logout()
.invalidateHttpSession(true)
.deleteCookies("JESSIONID")
.permitAll();
}
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
控制器
@RequestMapping(value = "/login", method = RequestMethod.GET)
public String logIn() {
return "login-custom";
}
@RequestMapping(value = "/home", method = RequestMethod.POST)
public String home() {
return "home";
}
JSP
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title></title>
<script type="text/javascript" src="/workdaybsa/js/jquery-1.10.2.min.js"></script>
<script language="javascript">
function login() {
$.ajax({
url: $('#loginForm').attr('action'),
type: 'POST',
data: $('#loginForm').serialize(),
dataType: "json",
success: function(response){
$('#loginSection').attr('style', 'display:none');
$('#selectionSection').removeAttr('style');
},
error: function (xhr, status, error) {
alert(status);
alert(error);
}
});
}
function proceed() {
$('form').attr('action', 'home');
$('form').submit();
}
</script>
</head>
<body>
<form id="loginForm" action="login" method="post">
<div id="loginSection">
<p>
<label for="username">Username</label>
<input type="text" id="username" name="username">
</p>
<p>
<label for="password">Password</label>
<input type="password" id="password" name="password">
</p>
<input type="button" value="Sign In" onclick="login()">
</div>
<div id="selectionSection" style="display:none">
<select id="selection">
<option value="">-- Select The Option --</option>
</select>
<input type="button" value="Continue" onclick="proceed()">
</div>
<input type="hidden" id="csrf" name="${_csrf.parameterName}" value="${_csrf.token}"/>
</form>
</body>
</html>
答案 0 :(得分:0)
CSRF令牌是一种防伪令牌,您需要使用Csrf-Token标头属性在每个请求上将其传递回Spring Security,即使它在隐藏的输入字段中,该属性也不会包含在ajax调用中。这就是CSRF验证失败并抛出403的原因。
提供了解决方案要无耻地复制粘贴答案,这是您需要的:
$.ajax({
url: route.url,
...
headers: {
'Csrf-Token': $('#csrf").val()
}
});