天天看點

五分鐘帶你玩轉SpringSecurity(八)基操勿6,帶你實作驗證碼功能

登入輸入随機驗證碼功能也是比價基礎的功能 spring security組成就是一大串過濾器鍊 首先過濾使用者是否正确 然後過濾狀态是否可用等,那麼驗證碼就是在使用者過濾器前再加入一個過濾器 如果驗證碼不正确直接傳回

KaptchaImageCodeConfig 

驗證碼樣式

@Configuration
public class KaptchaImageCodeConfig {
 
    @Bean
    public DefaultKaptcha getDefaultKaptcha() {
        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
        Properties properties = new Properties();
        properties.setProperty(Constants.KAPTCHA_BORDER, "yes");
        properties.setProperty(Constants.KAPTCHA_BORDER_COLOR, "192,192,192");
        properties.setProperty(Constants.KAPTCHA_IMAGE_WIDTH, "110");
        properties.setProperty(Constants.KAPTCHA_IMAGE_HEIGHT, "36");
        properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue");
        properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_FONT_SIZE, "28");
        properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_FONT_NAMES, "宋體");
        properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4");
        // 圖檔效果
        properties.setProperty(Constants.KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
        Config config = new Config(properties);
        defaultKaptcha.setConfig(config);
        return defaultKaptcha;
    }
}      

SpringSecurityConfig 

http.addFilterBefore(imageCodeValidateFilter, UsernamePasswordAuthenticationFilter.class) 将驗證碼過濾器鍊添加到使用者過濾器之前。

@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
 
    /**
     * 驗證碼過濾器
     */
    @Autowired
    private ImageCodeValidateFilter imageCodeValidateFilter;
 
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 驗證碼過濾器
        http.addFilterBefore(imageCodeValidateFilter, UsernamePasswordAuthenticationFilter.class)
            // 跳轉前台的位址
            .formLogin().loginPage("/loginPage")
            // 登入調用的接口位址
            .loginProcessingUrl("/login").successHandler(customAuthenticationSuccessHandler);
 
    }
}      

ImageCodeValidateFilter 

驗證碼過濾器

@Component("imageCodeValidateFilter")
public class ImageCodeValidateFilter extends OncePerRequestFilter {
 
    @Autowired
    SecurityProperties securityProperties;
 
    @Autowired
    CustomAuthenticationFailureHandler customAuthenticationFailureHandler;
 
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
        throws ServletException, IOException {
        // 1. 如果是post方式 的登入請求,則校驗輸入的驗證碼是否正确
        if ("/login".equals(request.getRequestURI()) && request.getMethod().equalsIgnoreCase("post")) {
            try {
                // 校驗驗證碼合法性
                validate(request);
            } catch (AuthenticationException e) {
                // 交給失敗處理器進行處理異常 也就是上文失敗傳回的json
                customAuthenticationFailureHandler.onAuthenticationFailure(request, response, e);
                // 一定要記得結束
                return;
            }
        }
        // 放行請求 往下執行過濾器
        filterChain.doFilter(request, response);
    }
 
    private void validate(HttpServletRequest request) {
        // 先擷取seesion中的驗證碼
        String sessionCode = (String)request.getSession().getAttribute(CODE_SESSION_KEY);
        // 擷取使用者輸入的驗證碼
        String inpuCode = request.getParameter("code");
        // 判斷是否正确
        if (StringUtils.isBlank(inpuCode)) {
            throw new ValidateCodeException("驗證碼不能為空");
        }
        if (!inpuCode.equalsIgnoreCase(sessionCode)) {
            throw new ValidateCodeException("驗證碼輸入錯誤");
        }
    }
}      

CodeController 

擷取驗證按接口

@Controller
public class CodeController {
    Logger logger = LoggerFactory.getLogger(getClass());
 
    @Autowired
    private DefaultKaptcha defaultKaptcha;
 
    @RequestMapping("/code/image")
    public void imageCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 1. 擷取驗證碼字元串
        String code = defaultKaptcha.createText();
        logger.info("生成的圖形驗證碼是:" + code);
        // 2. 字元串把它放到session中
        request.getSession().setAttribute(CODE_SESSION_KEY, code);
        // 3. 擷取驗證碼圖檔
        BufferedImage image = defaultKaptcha.createImage(code);
        // 4. 将驗證碼圖檔把它寫出去
        ServletOutputStream out = response.getOutputStream();
        ImageIO.write(image, "jpg", out);
    }
}