登入輸入随機驗證碼功能也是比價基礎的功能 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);
}
}