Spring Security 实现图片验证码登陆(二)

重构图形验证码接口
验证码基本参数可配置
验证码拦截的接口可配置
验证码的生成逻辑

图形验证码基本参数配置

这里写图片描述

/**
 * application.properties配置
 * Created by ZhuPengWei on 2017/11/28.
 */
@ConfigurationProperties(prefix = "spring.security")  //读取配置文件中所有以spring.security开头的文件
public class SecurityProperties {
    /**
     * 浏览器配置
     */
    private BrowserProperties browserProperties = new BrowserProperties();

    /**
     * 校验类型
     */
    private ValidateCodeProperties validateCodeProperties = new ValidateCodeProperties();
    ............
}
 /**
 * 生成图片配置
 * Created by ZhuPengWei on 2017/12/2.
 */
public class ImageCodeProperties {

     // 图片长度
    private int length = 4;
    // 图片宽度
    private int weight = 67;
    // 图片高度
    private int height = 23;
    // 图片失效时间
    private int expire = 60;
    // 图片过滤器 哪些情况下需要验证码
    private String url;

}

application.properties

#设置验证码的大小长度 过去时间等等
spring.security.validateCodeProperties.image.length = 5
spring.security.validateCodeProperties.image.weight = 67
spring.security.validateCodeProperties.image.height = 23
spring.security.validateCodeProperties.image.expire = 60
#哪些情况下需要生成图片验证码
spring.security.validateCodeProperties.image.url = /image,/image/*
/**
 * OncePerRequestFilter顾名思义,他能够确保在一次请求只通过一次filter,而不需要重复执行
 * 实现InitializingBean的目的是在其他参数组装完毕之后去初始化参数的值
 * Created by ZhuPengWei on 2017/12/1.
 */
public class ValidationCodeFilter extends OncePerRequestFilter implements InitializingBean {

    private AuthenticationFailureHandler authenticationFailureHandler;

    private SessionStrategy sessionStrategy = new HttpSessionSessionStrategy();

    private Set<String> urls = new HashSet<String>();

    private SecurityProperties securityProperties;
     // Spring工具类
  private AntPathMatcher pathMatcher = new AntPathMatcher();

    @Override
    public void afterPropertiesSet() throws ServletException {
        super.afterPropertiesSet();
        // 覆盖父类的实现
        String[] configUrls = StringUtils.split(securityProperties.getValidateCodeProperties().getImage().getUrl(), ",");
        for (String url : configUrls) {
            urls.add(url);
        }
        urls.add("/authentication/form");
    }
 @Override
protected void doFilterInternal( HttpServletRequest request, HttpServletResponse response, FilterChain filterChain ) throws ServletException, IOException
{
    boolean action = false;
    for ( String url : urls )
    {
        if ( pathMatcher.match( url, request.getRequestURI() ) )
        {
            action = true;
            break;
        }
    }
    if ( action && StringUtils.equalsIgnoreCase( "post", request.getMethod() ) )
    {
        try {
            validate( new ServletWebRequest( request ) );
        } catch ( ValidateCodeException e ) {
            authenticationFailureHandler.onAuthenticationFailure( request, response, e );
       /* 不继续执行 */
            return;
        }
    }
    /* 继续执行下一步 */
    filterChain.doFilter( request, response );
}

}
/**
 * security配置
 * Created by ZhuPengWei on 2017/11/27.
 */        
@Configuration
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {
    /* 处理密码加密解密逻辑 */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return (new BCryptPasswordEncoder());
    }

    @Autowired
    private SecurityProperties securityProperties;
    @Autowired
    private SelfDefineAuthenticationFailureHandler selfDefineAuthenticationFailureHandler;
    @Autowired
    private SelfDefineAuthenticationSuccessHandler selfDefineAuthenticationSuccessHandler;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        ValidationCodeFilter validationCodeFilter = new ValidationCodeFilter();
        /* 设置错误失败处理器 */
        validationCodeFilter.setAuthenticationFailureHandler(selfDefineAuthenticationFailureHandler);
        /* 注入 */
        validationCodeFilter.setSecurityProperties(securityProperties);
        /* 初始化方法 */
        validationCodeFilter.afterPropertiesSet();

        http.addFilterBefore(validationCodeFilter,UsernamePasswordAuthenticationFilter.class).formLogin() /* 表单登陆 */
            /* .loginPage("/index_standard.html") // 自定义登陆页面 */
            .loginPage("/authentication/require").permitAll().loginProcessingUrl("/authentication/form").successHandler(selfDefineAuthenticationSuccessHandler)
            .failureHandler(selfDefineAuthenticationFailureHandler).and().authorizeRequests() /* 请求授权 */
            .antMatchers("/index_standard.html",securityProperties.getBrowserProperties().getLoginPage(),"/code/image").permitAll() /* 匹配页面 */
            .anyRequest() /* 任何请求 */
            .authenticated() /* 都需要认证 */
            .and().csrf().disable(); /* 关闭跨站请求攻击 */
    }
}

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

常见的代码开发的一个思想
以增量的方式去适应变化 :当出现变化的时候,不如说图形验证码的逻辑出现改变了,原来的逻辑不满足了,那么处理的方式不是去修改原来的代码,而是新加了一段代码。
重构这件事情是永无止境的,代码永远可以变得更好

猜你喜欢

转载自blog.csdn.net/qq_36144258/article/details/79134970