Java Spring security validate captcha via filter的值错误
我正在研究SpringBoot,使用SpringSecurity进行身份验证登录。我完成了这部分。现在,我想在登录页面中实现captcha。我这样做了,但有时会出问题。这里是我的源代码 登录页面Java Spring security validate captcha via filter的值错误,java,spring-mvc,spring-boot,spring-security,captcha,Java,Spring Mvc,Spring Boot,Spring Security,Captcha,我正在研究SpringBoot,使用SpringSecurity进行身份验证登录。我完成了这部分。现在,我想在登录页面中实现captcha。我这样做了,但有时会出问题。这里是我的源代码 登录页面 <form th:action="@{/j_spring_security_check}" method="post"> <tr> <th align="left" width="30%"> &l
<form th:action="@{/j_spring_security_check}" method="post">
<tr>
<th align="left" width="30%">
<label for="userId">User Id</label>
</th>
<td width="70%">
<input type="text" style="width: 150px" name="userId" autocomplete="off"/>
</td>
</tr>
<tr>
<th align="left" width="30%">
Password
</th>
<td width="70%">
<input type="PASSWORD" style="width: 150px" name="password" autocomplete="off"/>
</td>
</tr>
<tr>
<th align="left" width="30%">
Answer
</th>
<td width="70%">
<input type="text" name="logonAnswer" style="width: 150px"/>
</td>
</tr>
<tr>
<td align="right">
</td>
<td align="left">
<div id="captcha"
style="cursor: pointer; height: 30px; width: 150px; display: inline-block; float: left"><img
th:src="@{/captcha}"/></div>
<div id="captchaRefresh" class="refresh-btn" title="Click to get other Captcha"></div>
</td>
</tr>
</form>
验证码验证过滤器中的
@Autowired
UserDetailsServiceImpl userDetailsService;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest req, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpSession session = request.getSession(false);
if (userDetailsService != null
&& request.getParameter("logonAnswer") != null
&& !request.getParameter("logonAnswer").equals("")
&& session != null && request.getParameter("logonAnswer").equalsIgnoreCase(session.getAttribute("wirecardmposcaptcha").toString())) {
userDetailsService.setCaptchaOK(true);
}
chain.doFilter(request, response);
}
和用户详细信息简化
private boolean captchaOK;
public void setCaptchaOK(boolean captchaOK) {
this.captchaOK = captchaOK;
}
@Override
@Transactional
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Users user = userRepository.findByUserId(username);
if (user == null) {
throw new UsernameNotFoundException("UserId or Password invalid");
}
if (!captchaOK)
throw new InternalAuthenticationServiceException("Invalid Captcha");
Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
Set<Roles> roles = user.getRoles();
for (Roles role : roles) {
grantedAuthorities.add(new SimpleGrantedAuthority(role.getRoleName()));
}
return new org.springframework.security.core.userdetails.User(user.getUserId(), user.getPassword(), user.getEnabled().equals("true"), true, true, true, grantedAuthorities);
}
因此,我在captcha过滤器中调试captchaOk的值多次更改。我不确定我的做法是否正确
请看一看并提出意见
谢谢。之前,我定制了一个过滤器来验证spring boot应用程序中的验证码。也许你的定制过滤器有问题。您可以参考我的实现: 1.CaptchaAuthenticationFilter:在创建验证代码时将其放入会话中,然后从会话中获取验证代码以在此处进行验证
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* The filter to verify captcha.
*/
public class CaptchaAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
private String processUrl;
public CaptchaAuthenticationFilter(String defaultFilterProcessesUrl, String failureUrl) {
super(defaultFilterProcessesUrl);
this.processUrl = defaultFilterProcessesUrl;
setAuthenticationFailureHandler(new SimpleUrlAuthenticationFailureHandler(failureUrl));
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res=(HttpServletResponse)response;
if(processUrl.equals(req.getServletPath()) && "POST".equalsIgnoreCase(req.getMethod())){
String expect = req.getSession().getAttribute("YZM").toString();
//remove from session
req.getSession().removeAttribute("YZM");
if (expect != null && !expect.equals(req.getParameter("verifyCode"))){
unsuccessfulAuthentication(req, res, new InsufficientAuthenticationException("Wrong verification code."));
return;
}
}
chain.doFilter(request, response);
}
@Override
public Authentication attemptAuthentication(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws AuthenticationException, IOException, ServletException {
return null;
}
}
2.将其配置为spring security:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
// add filter here
http.addFilterBefore(new CaptchaAuthenticationFilter("/login", "/login?error2"), UsernamePasswordAuthenticationFilter.class);
http.authorizeRequests()
.antMatchers("/").hasRole("USER")
.antMatchers("/index").hasRole("USER")
.antMatchers("/message/*").hasRole("USER")
.anyRequest().permitAll()
.and().formLogin().loginPage("/login").defaultSuccessUrl("/index").failureUrl("/login?error1").permitAll()
.and().rememberMe().tokenValiditySeconds(60*60*7).key("message")
.and().logout().logoutUrl("/logout").logoutSuccessUrl("/login").permitAll();
}
3.注意上面的failureUrl/login?error 2
。如果验证码验证失败,那么请求将被重定向到那里。您可以在页面上捕获错误,如下所示:
<div class="clearfix">
<div th:if="${param.error1}">
<div class="btn btn-xs btn-danger">
<i class="icon-bolt bigger-110"></i>
Wrong username or password!
</div>
</div>
<div th:if="${param.error2}">
<div class="btn btn-xs btn-danger">
<i class="icon-bolt bigger-110"></i>
Wrong verification code!
</div>
</div>
</div>
错误的用户名或密码!
错误的验证码!
之前,我定制了一个过滤器来验证spring boot应用程序中的验证码。也许你的定制过滤器有问题。您可以参考我的实现:
1.CaptchaAuthenticationFilter:在创建验证代码时将其放入会话中,然后从会话中获取验证代码以在此处进行验证
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* The filter to verify captcha.
*/
public class CaptchaAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
private String processUrl;
public CaptchaAuthenticationFilter(String defaultFilterProcessesUrl, String failureUrl) {
super(defaultFilterProcessesUrl);
this.processUrl = defaultFilterProcessesUrl;
setAuthenticationFailureHandler(new SimpleUrlAuthenticationFailureHandler(failureUrl));
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res=(HttpServletResponse)response;
if(processUrl.equals(req.getServletPath()) && "POST".equalsIgnoreCase(req.getMethod())){
String expect = req.getSession().getAttribute("YZM").toString();
//remove from session
req.getSession().removeAttribute("YZM");
if (expect != null && !expect.equals(req.getParameter("verifyCode"))){
unsuccessfulAuthentication(req, res, new InsufficientAuthenticationException("Wrong verification code."));
return;
}
}
chain.doFilter(request, response);
}
@Override
public Authentication attemptAuthentication(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws AuthenticationException, IOException, ServletException {
return null;
}
}
2.将其配置为spring security:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
// add filter here
http.addFilterBefore(new CaptchaAuthenticationFilter("/login", "/login?error2"), UsernamePasswordAuthenticationFilter.class);
http.authorizeRequests()
.antMatchers("/").hasRole("USER")
.antMatchers("/index").hasRole("USER")
.antMatchers("/message/*").hasRole("USER")
.anyRequest().permitAll()
.and().formLogin().loginPage("/login").defaultSuccessUrl("/index").failureUrl("/login?error1").permitAll()
.and().rememberMe().tokenValiditySeconds(60*60*7).key("message")
.and().logout().logoutUrl("/logout").logoutSuccessUrl("/login").permitAll();
}
3.注意上面的failureUrl/login?error 2
。如果验证码验证失败,那么请求将被重定向到那里。您可以在页面上捕获错误,如下所示:
<div class="clearfix">
<div th:if="${param.error1}">
<div class="btn btn-xs btn-danger">
<i class="icon-bolt bigger-110"></i>
Wrong username or password!
</div>
</div>
<div th:if="${param.error2}">
<div class="btn btn-xs btn-danger">
<i class="icon-bolt bigger-110"></i>
Wrong verification code!
</div>
</div>
</div>
错误的用户名或密码!
错误的验证码!