圖形驗證碼是用于驗證用戶身份的一種方式,通常在網(wǎng)站注冊、登錄或進行某些敏感操作時會使用。它通過展示一個包含隨機字符或數(shù)字的圖形,要求用戶輸入相應(yīng)的字符或數(shù)字來證明其為真人而非機器人。圖形驗證碼能有效地防止機器人攻擊和惡意注冊行為,提高網(wǎng)站的安全性。
本文將基于 SpringBoot 和原生的 Java awt 包,完成圖形驗證碼的實現(xiàn),源碼在 項目倉庫 中,需要者可自助參考。
一、導(dǎo)入依賴
在實現(xiàn)圖形驗證碼之前,首先要導(dǎo)入依賴,比如 SpringBoot 依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
awt 包屬于 Java 原生包,無需導(dǎo)入三方 maven 依賴,只需引入 JDK 即可。
二、編寫工具類
接下來,就開始開發(fā)驗證碼的工具類,包括驗證碼配置、生成隨機數(shù)、生成隨機顏色、編寫創(chuàng)建圖片方法、編寫構(gòu)建函數(shù),下面將逐一介紹。
2.1 驗證碼配置
首先是驗證碼的配置,創(chuàng)建 CreateVerifyCode
類,創(chuàng)建相應(yīng)字段,包括字符個數(shù)、圖片高度、圖片寬度、干擾個數(shù)等參數(shù),定義如下。
@ApiModelProperty(value = "驗證碼字符個數(shù)")
private int charactersNumber = 4;
@ApiModelProperty(value = "圖片高度")
private int imagePeripheralHeight = 40;
@ApiModelProperty(value = "圖片寬度")
private int imagePeripheralWidth = 160;
@ApiModelProperty(value = "干擾線數(shù)")
private int lineCount = 20;
2.2 生成隨機數(shù)
新建一個方法 randomStr
,用于實現(xiàn)生成隨機數(shù)的功能,代碼如下。
@ApiOperation(value = "隨機生成驗證碼")
public String randomStr(int size) {
String str1 = "0123456789";
String str2 = "";
for (int i = 0; i < size; i++) {
double randomIndex = Math.random();
double randomNumber = randomIndex * (str1.length() - 1);
str2 += str1.charAt((int) randomNumber);
}
return str2;
}
2.3 生成隨機顏色
新建一個方法 getRandColor
,用于實現(xiàn)生成隨機顏色的功能,代碼如下。
@ApiOperation(value = "隨機生成驗證碼顏色")
private Color getRandColor(int color1, int color2) {
color1 = color1 > 255 ? 255 : color1;
color2 = color2 > 255 ? 255 : color2;
return new Color(color1 + random.nextInt(color2 - color1), color1 + random.nextInt(color2 - color1), color1 + random.nextInt(color2 - color1));
}
2.4 編寫創(chuàng)建圖片方法
有了驗證碼配置之后,新建一個方法 creatImage
,用于實現(xiàn)圖形驗證碼圖片創(chuàng)建的邏輯,代碼如下。
@ApiOperation(value = "圖片生成工具類")
private void creatImage(String code) {
if(ZwzNullUtils.isNull(code)){
throw new ZwzException("圖形驗證碼過期了,再生成個新的哦!");
}
this.code = code;
buffImg = new BufferedImage(imagePeripheralWidth, imagePeripheralHeight, BufferedImage.TYPE_INT_RGB);
Graphics g = buffImg.getGraphics();
g.setColor(getRandColor(200, 250));
g.fillRect(0, 0, imagePeripheralWidth, imagePeripheralHeight);
Font font = new Font("Fixedsys", Font.BOLD, imagePeripheralHeight - 5);
g.setFont(font);
float yawpRate = 0.01f;
int area = (int) (yawpRate * imagePeripheralWidth * imagePeripheralHeight);
for (int i = 0; i < area; i++) {
buffImg.setRGB(random.nextInt(imagePeripheralWidth), random.nextInt(imagePeripheralHeight), random.nextInt(255));
}
for (int i = 0; i < lineCount; i++) {
int xs = random.nextInt(imagePeripheralWidth);
int ys = random.nextInt(imagePeripheralHeight);
int xe = xs + random.nextInt(imagePeripheralWidth);
int ye = ys + random.nextInt(imagePeripheralHeight);
g.setColor(getRandColor(2, 254));
g.drawLine(xs, ys, xe, ye);
}
for (int i = 0; i < code.length(); i++) {
String strRand = code.substring(i, i + 1);
g.setColor(getRandColor(2, 254));
g.drawString(strRand, i * (imagePeripheralWidth / charactersNumber) + 3, imagePeripheralHeight - 8);
}
}
2.5 編寫構(gòu)建函數(shù)
為了用盡可能精簡的代碼實現(xiàn)圖形驗證碼,構(gòu)造函數(shù)是比不可少的,開發(fā)者可以在構(gòu)建對象時直接傳入?yún)?shù),實現(xiàn)圖形驗證碼的設(shè)計,代碼如下。
public CreateVerifyCode(int imageWidth, int imageHeight, int codeCount, int lineCount, String code) {
this.imagePeripheralWidth = imageWidth;
this.imagePeripheralHeight = imageHeight;
this.charactersNumber = codeCount;
this.lineCount = lineCount;
creatImage(code);
}
三、編寫接口
工具類編寫完成后,就開始設(shè)計 API 接口了,可以分為驗證碼初始化和圖片返回。
3.1 驗證碼初始化
首先定義一個 init 接口,用戶請求該接口時,系統(tǒng)利用 Java 的 UUID,生成一個隨機字符串,并隨機生成一個四位數(shù)字,放入緩存,返回該隨機字符串,代碼如下。
@RequestMapping(value = "/init", method = RequestMethod.GET)
@ApiOperation(value = "初始化驗證碼")
public Result<Object> init() {
String codeId = UUID.randomUUID().toString().replace("-","");
redisTemplate.opsForValue().set(codeId, new CreateVerifyCode().randomStr(4),2L, TimeUnit.MINUTES);
return ResultUtil.data(codeId);
}
接口測試結(jié)果如下,接口返回了一個隨機字符串:bdb3cc192cf147eda20afa5e5d22bd8c
。
3.2 圖片返回
前端收到隨機字符串 bdb3cc192cf147eda20afa5e5d22bd8c
后,再次請求,拿走驗證碼圖片,核心代碼如下。
@RequestMapping(value = "/draw/{captchaId}", method = RequestMethod.GET)
@ApiOperation(value = "根據(jù)驗證碼ID獲取圖片")
public void draw(@PathVariable("captchaId") String captchaId, HttpServletResponse response) throws IOException {
String codeStr = redisTemplate.opsForValue().get(captchaId);
CreateVerifyCode createVerifyCode = new CreateVerifyCode(116,36,4,10, codeStr);
response.setContentType("image/png");
createVerifyCode.write(response.getOutputStream());
}
首先根據(jù)隨機字符串,在 redis 中拿到驗證碼的值,在調(diào)用驗證碼工具類生成圖片,返回前端。
3.3 驗證碼過濾
系統(tǒng)集成了 Spring Security,需要引入并重寫 WebSecurityConfig 類,重寫 securityFilterChain 方法。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests().requestMatchers("/zwz/dictData/getByType/**","/zwz/file/view/**","/zwz/user/regist","/zwz/common/**","/*/*.js","/*/*.css","/*/*.png","/*/*.ico", "/swagger-ui.html").permitAll()
.and().formLogin().loginPage("/zwz/common/needLogin").loginProcessingUrl("/zwz/login").permitAll()
.successHandler(authenticationSuccessHandler).failureHandler(authenticationFailHandler).and()
.headers().frameOptions().disable().and()
.logout()
.permitAll()
.and()
.authorizeHttpRequests()
.anyRequest()
.authenticated()
.and()
.cors().and()
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.exceptionHandling().accessDeniedHandler(zwzAccessDeniedHandler)
.and()
.authenticationProvider(authenticationProvider())
.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(imageValidateFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
對于通過驗證碼的請求,給與放行,核心代碼如下:文章來源:http://www.zghlxwxcb.cn/news/detail-472057.html
@Override
@ApiOperation(value = "驗證碼過濾")
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
Boolean filterFlag = false;
for(String requestURI : captchaProperties.getVerification()){
if(pathMatcher.match(requestURI, request.getRequestURI())){
filterFlag = true;
break;
}
}
if(!filterFlag) {
filterChain.doFilter(request, response);
return;
}
String verificationCodeId = request.getParameter("captchaId");
String userInputCode = request.getParameter("code");
if(ZwzNullUtils.isNull(userInputCode) || ZwzNullUtils.isNull(verificationCodeId)){
ResponseUtil.out(response, ResponseUtil.resultMap(RESPONSE_FAIL_FLAG,RESPONSE_CODE_FAIL_CODE,"驗證碼為空"));
return;
}
String codeAnsInRedis = redisTemplate.opsForValue().get(verificationCodeId);
if(ZwzNullUtils.isNull(codeAnsInRedis)){
ResponseUtil.out(response, ResponseUtil.resultMap(RESPONSE_FAIL_FLAG,RESPONSE_CODE_FAIL_CODE,"已過期的驗證碼,需要重新填寫"));
return;
}
if(!Objects.equals(codeAnsInRedis.toLowerCase(),userInputCode.toLowerCase())) {
ResponseUtil.out(response, ResponseUtil.resultMap(RESPONSE_FAIL_FLAG,RESPONSE_CODE_FAIL_CODE,"驗證碼不正確"));
return;
}
redisTemplate.delete(verificationCodeId);
filterChain.doFilter(request, response);
}
最終,基于 SpringBoot+原生 awt,實現(xiàn)花花綠綠的圖形驗證碼。文章來源地址http://www.zghlxwxcb.cn/news/detail-472057.html
到了這里,關(guān)于SpringBoot+原生awt,實現(xiàn)花花綠綠的圖形驗證碼的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!