Spring security的图片验证码方案二

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xiaoyaoyulinger/article/details/78625319

方案二是使用spring security的过滤器来拦截登录请求,从而校验验证码。在方案一的时候我已经尝试过使用过滤器,但是当时对spring security内部实现原理一无所知,尝试了多次还是以失败告终。这里简单叙述一下spring security的登录验证机制:

Spring security使用众多的过滤器对url进行拦截,以此来进行权限管理。Spring security不允许我们修改默认的filter实现,但是可以加入自己的filter。登录验证的流程是,用户登陆会被AuthenticationProcessingFilter拦截,调用AuthenticationManager的实现,而AuthenticationManager会调用ProviderManager来获取用户验证信息。如果验证通过会将用户的权限信息封装成User对象放到spring的全局缓存SecurityContextHolder中,以备后面访问资源时使用。忽略验证用户信息的部分,我们可以通过AuthenticationProcessingFilter来检验验证码,并达到验证失败时拒绝用户登录的目的。

图片验证码的实现方法已经在上一篇博客中有阐述,大家可以参考spring security图片验证码方案一,这里只介绍拦截器的写法。

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;

/**
 * 校验验证码
 */
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();

            //销毁验证码
            req.getSession().removeAttribute("YZM");

            if (expect != null && !expect.equals(req.getParameter("verifyCode"))){
                unsuccessfulAuthentication(req, res, new InsufficientAuthenticationException("验证码错误"));
                return;
            }
        }
        chain.doFilter(request, response);
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) 
        throws AuthenticationException, IOException, ServletException {
        return null;
    }
}
processUrl是spring security拦截的请求地址,failureUrl是验证失败时的跳转地址。在生成验证码的时候,要将验证码存到session中。验证时从session中获取验证码,并将session中的验证码移除,否则可以重复登录(使用浏览器的重发功能)。然后将自己的过滤器加到spring security的过滤器链中。

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception{
        //auth.authenticationProvider(authenticationProvider());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
        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();
    }
}



猜你喜欢

转载自blog.csdn.net/xiaoyaoyulinger/article/details/78625319
今日推荐