欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

簡單聊聊Java中驗(yàn)證碼功能的實(shí)現(xiàn)

 更新時(shí)間:2023年06月07日 09:58:05   作者:god23bin  
相信大家都經(jīng)常接觸到驗(yàn)證碼的,畢竟平時(shí)上網(wǎng)也能遇到各種驗(yàn)證碼,需要我們輸入驗(yàn)證碼進(jìn)行驗(yàn)證我們是人類,本篇文章就從這幾個(gè)方面出發(fā)說說驗(yàn)證碼,廢話不多說,下面開始正文

前言

大家好,我是 god23bin,今天說說驗(yàn)證碼功能的實(shí)現(xiàn),相信大家都經(jīng)常接觸到驗(yàn)證碼的,畢竟平時(shí)上網(wǎng)也能遇到各種驗(yàn)證碼,需要我們輸入驗(yàn)證碼進(jìn)行驗(yàn)證我們是人類,而不是機(jī)器人。

驗(yàn)證碼有多種類型,比如圖片驗(yàn)證碼、短信驗(yàn)證碼和郵件驗(yàn)證碼等等,雖說多種類型,圖片也好,短信也好,郵件也好,都是承載驗(yàn)證碼的載體,最主要的核心就是一個(gè)驗(yàn)證碼的生成、存儲和校驗(yàn)。

本篇文章就從這幾個(gè)方面出發(fā)說說驗(yàn)證碼,廢話不多說,下面開始正文。

實(shí)現(xiàn)思路

驗(yàn)證碼驗(yàn)證的功能,其實(shí)現(xiàn)思路還是挺簡單的,不論是圖片驗(yàn)證碼、短信驗(yàn)證碼還是郵件驗(yàn)證碼,無非就以下幾點(diǎn):

  • 驗(yàn)證碼本質(zhì)就是一堆字符的組合(數(shù)字也好,英文字母也好),后端生成驗(yàn)證碼,并存儲到某個(gè)位置(比如存儲到 Redis,并設(shè)置驗(yàn)證碼的過期時(shí)間)。
  • 返回驗(yàn)證碼給前端頁面、發(fā)送短信驗(yàn)證碼給用戶或者發(fā)送郵件驗(yàn)證碼給用戶。驗(yàn)證碼可以是以文字顯示或者圖片顯示。
  • 用戶輸入看到的驗(yàn)證碼,并提交驗(yàn)證(驗(yàn)證也可以忽略大小寫,當(dāng)然具體看需求)。
  • 后端將用戶輸入的驗(yàn)證碼拿過來進(jìn)行校驗(yàn),對比用戶輸入的驗(yàn)證碼是否和后端生成的一致,一致就驗(yàn)證成功,否則驗(yàn)證失敗。

驗(yàn)證碼的生成

首先,需要知道的就是驗(yàn)證碼的生成,這就涉及到生成驗(yàn)證碼的算法,可以自己純手寫,也可以使用人家提供的工具,這里我就介紹下面 4 種生成驗(yàn)證碼的方式。

1. 純原生手寫生成文本驗(yàn)證碼

需求:隨機(jī)產(chǎn)生一個(gè) n 位的驗(yàn)證碼,每位可能是數(shù)字、大寫字母、小寫字母。

實(shí)現(xiàn):本質(zhì)就是隨機(jī)生成字符串,字符串可包含數(shù)字、大寫字母、小寫字母。

準(zhǔn)備一個(gè)包含數(shù)字、大寫字母、小寫字母的字符串,借助 Random 類,循環(huán) n 次隨機(jī)獲取字符串的下標(biāo),就能拼接出一個(gè)隨機(jī)字符組成的字符串了。

package cn.god23bin.demo.util;
import java.util.Random;
public class MyCaptchaUtil {
	/**
     * 生成 n 位驗(yàn)證碼
     * @param n 位數(shù)
     * @return n 位驗(yàn)證碼
     **/
    public static String generateCode(int n) {
        String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < n; i++) {
            int index = random.nextInt(chars.length());
            sb.append(chars.charAt(index));
        }
        return sb.toString();
    }
}

2. 純原生手寫生成圖片驗(yàn)證碼

實(shí)現(xiàn):使用 Java 的 awt 和 swing 庫來生成圖片驗(yàn)證碼。下面使用 BufferedImage 類創(chuàng)建一個(gè)指定大小的圖片,然后隨機(jī)生成 n 個(gè)字符,將其畫在圖片上,將生成的字符和圖片驗(yàn)證碼放到哈希表返回。后續(xù)我們就可以拿到驗(yàn)證碼的文本值,并且可以將圖片驗(yàn)證碼輸出到指定的輸出流中。

package cn.god23bin.demo.util;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.HashMap;
import java.util.Map;
public class MyCaptchaUtil {
	/**
     * 生成 n 位的圖片驗(yàn)證碼
     * @param n 位數(shù)
     * @return 哈希表,code 獲取文本驗(yàn)證碼,img 獲取 BufferedImage 圖片對象
     **/
    public static Map<String, Object> generateCodeImage(int n) {
        int width = 100, height = 50;
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = image.createGraphics();
        g.setColor(Color.LIGHT_GRAY);
        g.fillRect(0, 0, width, height);
        String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        Random random = new Random();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < n; i++) {
            int index = random.nextInt(chars.length());
            char c = chars.charAt(index);
            sb.append(c);
            g.setColor(new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255)));
            g.setFont(new Font("Arial", Font.BOLD, 25));
            g.drawString(Character.toString(c), 20 + i * 15, 25);
        }
        Map<String, Object> res = new HashMap<>();
        res.put("code", sb.toString());
        res.put("img", image);
        return res;
    }
}

我們可以寫一個(gè)獲取驗(yàn)證碼的接口,以二進(jìn)制流輸出返回給前端,前端可以直接使用 img 標(biāo)簽來顯示我們返回的圖片,只需在 src 屬性賦值我們的獲取驗(yàn)證碼接口。

@RequestMapping("/captcha")
@RestController
public class CaptchaController {
    @GetMapping("/code/custom")
    public void getCode(HttpServletResponse response) {
        Map<String, Object> map = MyCaptchaUtil.generateCodeImage(5);
        System.out.println(map.get("code"));
        BufferedImage img = (BufferedImage) map.get("img");
        // 設(shè)置響應(yīng)頭,防止緩存
        response.setHeader("Cache-Control", "no-store, no-cache");
        response.setContentType("image/png");
        try {
            ImageIO.write(img, "png", response.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3. 使用 Hutool 工具生成圖形驗(yàn)證碼

引入依賴:可以單獨(dú)引入驗(yàn)證碼模塊或者全部模塊都引入

<!-- 驗(yàn)證碼模塊 -->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-captcha</artifactId>
    <version>5.8.15</version>
</dependency>
<!-- 全部模塊都引入 -->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.15</version>
</dependency>

生成線段干擾的驗(yàn)證碼:

// 設(shè)置圖形驗(yàn)證碼的寬和高,同時(shí)生成了驗(yàn)證碼,可以通過 lineCaptcha.getCode() 獲取文本驗(yàn)證碼
LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 100);

生成圓圈干擾的驗(yàn)證碼:

// 設(shè)置圖形驗(yàn)證碼的寬、高、驗(yàn)證碼字符數(shù)、干擾元素個(gè)數(shù)
CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(200, 100, 4, 20);

生成扭曲干擾的驗(yàn)證碼:

// 定義圖形驗(yàn)證碼的寬、高、驗(yàn)證碼字符數(shù)、干擾線寬度
ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(200, 100, 4, 4);

獲取驗(yàn)證碼接口:

@RequestMapping("/captcha")
@RestController
public class CaptchaController {
    @GetMapping("/code/hutool")
    public void getCodeByHutool(HttpServletResponse response) {
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 100);
        System.out.println("線段干擾的驗(yàn)證碼:" + lineCaptcha.getCode());
        // 設(shè)置響應(yīng)頭,防止緩存
        response.setHeader("Cache-Control", "no-store, no-cache");
        response.setContentType("image/png");
        try {
            lineCaptcha.write(response.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

4. 使用 Kaptcha 生成驗(yàn)證碼

Kaptcha 是谷歌的一個(gè)生成驗(yàn)證碼工具包,我們簡單配置其屬性就可以實(shí)現(xiàn)驗(yàn)證碼的驗(yàn)證功能。

引入依賴項(xiàng):它只有一個(gè)版本:2.3.2

<dependency>
    <groupId>com.github.penggle</groupId>
    <artifactId>kaptcha</artifactId>
    <version>2.3.2</version>
</dependency>

簡單看看 kaptcha 屬性:

屬性描述默認(rèn)值
kaptcha.border圖片邊框,合法值:yes , noyes
kaptcha.border.color邊框顏色,合法值: r,g,b (and optional alpha) 或者 white,black,blue.black
kaptcha.border.thickness邊框厚度,合法值:>01
kaptcha.image.width圖片寬200
kaptcha.image.height圖片高50
kaptcha.producer.impl圖片實(shí)現(xiàn)類com.google.code.kaptcha.impl.DefaultKaptcha
kaptcha.textproducer.impl文本實(shí)現(xiàn)類com.google.code.kaptcha.text.impl.DefaultTextCreator
kaptcha.textproducer.char.string文本集合,驗(yàn)證碼值從此集合中獲取abcde2345678gfynmnpwx
kaptcha.textproducer.char.length驗(yàn)證碼長度5
kaptcha.textproducer.font.names字體Arial, Courier
kaptcha.textproducer.font.size字體大小40px
kaptcha.textproducer.font.color字體顏色,合法值: r,g,b 或者 white,black,blue.black
kaptcha.textproducer.char.space文字間隔2
kaptcha.noise.impl干擾實(shí)現(xiàn)類com.google.code.kaptcha.impl.DefaultNoise
kaptcha.noise.color干擾顏色,合法值: r,g,b 或者 white,black,blue.black
kaptcha.obscurificator.impl圖片樣式: 水紋com.google.code.kaptcha.impl.WaterRipple 魚眼com.google.code.kaptcha.impl.FishEyeGimpy 陰影com.google.code.kaptcha.impl.ShadowGimpycom.google.code.kaptcha.impl.WaterRipple
kaptcha.background.impl背景實(shí)現(xiàn)類com.google.code.kaptcha.impl.DefaultBackground
kaptcha.background.clear.from背景顏色漸變,開始顏色light grey
kaptcha.background.clear.to背景顏色漸變,結(jié)束顏色white
kaptcha.word.impl文字渲染器com.google.code.kaptcha.text.impl.DefaultWordRenderer
kaptcha.session.keysession keyKAPTCHA_SESSION_KEY
kaptcha.session.datesession dateKAPTCHA_SESSION_DATE

簡單配置下 Kaptcha:

package cn.god23bin.demo.config;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Properties;
@Configuration
public class KaptchaConfig {
    /**
     * 配置生成圖片驗(yàn)證碼的bean
     * @return
     */
    @Bean(name = "kaptchaProducer")
    public DefaultKaptcha getKaptchaBean() {
        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
        Properties properties = new Properties();
        properties.setProperty("kaptcha.border", "no");
        properties.setProperty("kaptcha.textproducer.font.color", "black");
        properties.setProperty("kaptcha.textproducer.char.space", "4");
        properties.setProperty("kaptcha.textproducer.char.length", "4");
        properties.setProperty("kaptcha.textproducer.char.string", "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
        Config config = new Config(properties);
        defaultKaptcha.setConfig(config);
        return defaultKaptcha;
    }
}

也是和 Hutool 一樣,很簡單就能生成驗(yàn)證碼了。如下:

// 生成文字驗(yàn)證碼
String text = kaptchaProducer.createText();
// 生成圖片驗(yàn)證碼
BufferedImage image = kaptchaProducer.createImage(text);

獲取驗(yàn)證碼接口:

@RequestMapping("/captcha")
@RestController
public class CaptchaController {
    @Autowired
    private Producer kaptchaProducer;
    @GetMapping("/code/kaptcha")
    public void getCodeByKaptcha(HttpServletResponse response) {
        // 生成文字驗(yàn)證碼
        String text = kaptchaProducer.createText();
        System.out.println("文字驗(yàn)證碼:" + text);
        // 生成圖片驗(yàn)證碼
        BufferedImage image = kaptchaProducer.createImage(text);
        // 設(shè)置響應(yīng)頭,防止緩存
        response.setHeader("Cache-Control", "no-store, no-cache");
        response.setContentType("image/jpeg");
        try {
            ImageIO.write(image, "jpg", response.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

驗(yàn)證碼的存儲與校驗(yàn)

上面的驗(yàn)證碼的生成,就僅僅是生成驗(yàn)證碼,并沒有將驗(yàn)證碼存儲在后端,所以現(xiàn)在我們需要做的是:將驗(yàn)證碼存儲起來,便于后續(xù)的校驗(yàn)對比。

那么存儲到什么地方呢?如果你沒接觸過 Redis,那么第一次的想法可能就是存儲到關(guān)系型數(shù)據(jù)庫中,比如 MySQL。想當(dāng)年,我最開始的想法就是這樣哈哈哈。

不過,目前用得最多的就是將驗(yàn)證碼存儲到 Redis 中,好處就是減少了數(shù)據(jù)庫的壓力,加快了驗(yàn)證碼的讀取效率,還能輕松設(shè)置驗(yàn)證碼的過期時(shí)間。

簡單配置 Redis

引入 Redis 依賴項(xiàng):

我們使用 Spring Data Redis,它提供了 RedisTemplate 和 StringRedisTemplate 模板類,簡化了我們使用 Java 進(jìn)行 Redis 的操作。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

簡單配置下 Redis:

spring:
  redis:
    host: localhost
    port: 6379
    database: 1
    timeout: 5000
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        // 大多數(shù)情況,都是選用<String, Object>
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);
        // 使用JSON的序列化對象,對數(shù)據(jù) key 和 value 進(jìn)行序列化轉(zhuǎn)換
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        // ObjectMapper 是 Jackson 的一個(gè)工作類,作用是將 JSON 轉(zhuǎn)成 Java 對象,即反序列化。或?qū)?Java 對象轉(zhuǎn)成 JSON,即序列化
        ObjectMapper mapper = new ObjectMapper();
        // 設(shè)置序列化時(shí)的可見性,第一個(gè)參數(shù)是選擇序列化哪些屬性,比如時(shí)序列化 setter? 還是 filed? 第二個(gè)參數(shù)是選擇哪些修飾符權(quán)限的屬性來序列化,比如 private 或者 public,這里的 any 是指對所有權(quán)限修飾的屬性都可見(可序列化)
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        jackson2JsonRedisSerializer.setObjectMapper(mapper);
        // 設(shè)置 RedisTemplate 模板的序列化方式為 jacksonSeial
        template.setDefaultSerializer(jackson2JsonRedisSerializer);
        return template;
    }
}

將驗(yàn)證碼存儲到 Redis

將驗(yàn)證碼存儲到 Redis 設(shè)置 5 分鐘的過期時(shí)間,Redis 是 Key Value 這種形式存儲的,所以需要約定好 Key 的命名規(guī)則。

命名的時(shí)候,為了區(qū)分為每個(gè)用戶生成的驗(yàn)證碼,所以需要一個(gè)標(biāo)識,剛好可以通過當(dāng)前請求的 HttpSession 中的 SessionID 作為唯一標(biāo)識,拼接到 Key 的名稱中。

當(dāng)然,也不一定使用 SessionID 作為唯一標(biāo)識,如果能知道其他的,也可以用其他的作為標(biāo)識,比如拼接用戶的手機(jī)號。

實(shí)現(xiàn):

@RequestMapping("/captcha")
@RestController
public class CaptchaController {
    @Autowired
    private Producer kaptchaProducer;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @GetMapping("/code")
    public void getCode(HttpServletRequest request, HttpServletResponse response) {
        // 生成文字驗(yàn)證碼
        String text = kaptchaProducer.createText();
        System.out.println("文字驗(yàn)證碼:" + text);
        // 生成圖片驗(yàn)證碼
        BufferedImage image = kaptchaProducer.createImage(text);
        // 存儲到 Redis 設(shè)置 5 分鐘的過期時(shí)間
        // 約定好存儲的 Key 的命名規(guī)則,這里使用 code_sessionId_type_1 表示圖形驗(yàn)證碼
        // Code_sessionId_Type_1:分為 3 部分,code 表明是驗(yàn)證碼,sessionId 表明是給哪個(gè)用戶的驗(yàn)證碼,type_n 表明驗(yàn)證碼類型,n 為 1 表示圖形驗(yàn)證碼,2 表示短信驗(yàn)證碼,3 表示郵件驗(yàn)證碼
        String key = "code_" + request.getSession().getId() + "_type_1";
        redisTemplate.opsForValue().set(key, text, 5, TimeUnit.SECONDS);
        response.setHeader("Cache-Control", "no-store, no-cache");
        response.setContentType("image/jpeg");
        try {
            ImageIO.write(image, "jpg", response.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

上面代碼中有一個(gè)額外的設(shè)計(jì)就是,由于發(fā)送的驗(yàn)證碼有多種類型(圖形驗(yàn)證碼、短信驗(yàn)證碼、郵件驗(yàn)證碼),所以加多了一個(gè) type_n 來標(biāo)識當(dāng)前存儲的驗(yàn)證碼是什么類型的,方便以后出現(xiàn)問題快速定位。

實(shí)際上,這里的命名規(guī)則,可以根據(jù)你的具體需求來定制,又比如說,登錄的時(shí)候需要驗(yàn)證碼、注冊的時(shí)候也需要驗(yàn)證碼、修改用戶密碼的時(shí)候也需要驗(yàn)證碼,為了便于出現(xiàn)問題進(jìn)行定位,也可以繼續(xù)加多一個(gè)標(biāo)識 when_n,n 為 1 表示注冊、n 為 2 表示登錄,以此類推。

校驗(yàn)

我們模擬登錄的時(shí)候進(jìn)行驗(yàn)證碼的校驗(yàn),使用一個(gè) LoginDTO 對象來接收前端的登錄相關(guān)的參數(shù)。

package cn.god23bin.demo.model.domain.dto;
import lombok.Data;
@Data
public class LoginDTO {
    private String username;
    private String password;
    /**
     * 驗(yàn)證碼
     */
    private String code;
}

寫一個(gè)登錄接口,登錄的過程中,校驗(yàn)用戶輸入的驗(yàn)證碼。

@RequestMapping("/user")
@RestController
public class UserController {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @PostMapping("/login")
    public Result<String> login(@RequestBody LoginDTO loginDTO, HttpServletRequest request) {
        if (!"root".equals(loginDTO.getUsername()) || !"123456".equals(loginDTO.getPassword())) {
            return Result.fail("登錄失敗!賬號或密碼不正確!");
        }
        // 校驗(yàn)用戶輸入的驗(yàn)證碼
        String code = loginDTO.getCode();
        String codeInRedis = (String) redisTemplate.opsForValue().get("code_" + request.getSession().getId() + "_type_1");
        if (!code.equals(codeInRedis)) {
            return Result.fail("驗(yàn)證碼不正確!");
        }
        return Result.ok("登錄成功!");
    }
}

至此,便完成了驗(yàn)證碼功能的實(shí)現(xiàn)。

獲取驗(yàn)證碼的安全設(shè)計(jì)

驗(yàn)證碼功能的實(shí)現(xiàn)現(xiàn)在是OK的,但還有一點(diǎn)需要注意,那就是防止驗(yàn)證碼被隨意調(diào)用獲取,或者被大量調(diào)用。如果不做限制,那么誰都能調(diào)用,就非常大的可能會被攻擊了。

我們上面實(shí)現(xiàn)的驗(yàn)證碼功能是圖形驗(yàn)證碼,是校驗(yàn)用戶從圖形驗(yàn)證碼中看到后輸入的數(shù)字字母組合跟后端生成的組合是否是一致的。對于圖形驗(yàn)證碼,到這里就可以了,不用限制(當(dāng)然想限制也可以)。但是對于短信驗(yàn)證碼,就還不可以。我們需要額外考慮一些防刷機(jī)制,以保障系統(tǒng)的安全性和可靠性(因?yàn)榘l(fā)短信是要錢的?。。?/p>

對于短信來說,一種常見的攻擊方式是「短信轟炸」,攻擊者通過自動批量提交手機(jī)號碼、模擬IP等手段,對系統(tǒng)進(jìn)行大規(guī)模的短信請求,從而消耗資源或干擾正常業(yè)務(wù)。為了應(yīng)對這種情況,我們需要設(shè)計(jì)一些防刷機(jī)制。

防刷機(jī)制

目前我了解到的防刷機(jī)制有下面幾種,如果你有別的方法,歡迎評論說出來噢!

  • 圖形驗(yàn)證碼或者滑動驗(yàn)證:發(fā)送短信前先使用圖形驗(yàn)證碼或者滑動進(jìn)行驗(yàn)證,驗(yàn)證成功才能調(diào)用發(fā)送短信驗(yàn)證碼的接口。
  • 時(shí)間限制:從用戶點(diǎn)擊發(fā)送短信驗(yàn)證碼開始,前端進(jìn)行一個(gè) 60 秒的倒數(shù),在這 60 秒之內(nèi),用戶無法提交發(fā)送信息的請求的,這樣就限制了發(fā)送短信驗(yàn)證碼的接口的調(diào)用次數(shù)。不過這種方式,如果被攻擊者知道了發(fā)送短信的接口,那也是會被刷的。
  • 手機(jī)號限制:對使用同一個(gè)手機(jī)號碼進(jìn)行注冊或者其他發(fā)送短信驗(yàn)證碼的操作的時(shí)候,系統(tǒng)可以對這個(gè)手機(jī)號碼進(jìn)行限制,例如,一天只能發(fā)送 5 條短信驗(yàn)證碼,超出限制則做出提示(如:系統(tǒng)繁忙,請稍后再試)。然而,這也只能夠避免人工手動刷短信而已,對于批量使用不同手機(jī)號碼來刷短信的機(jī)器,同樣是會被刷。
  • IP地址限制:記錄請求的IP地址,并對同一 IP 地址的請求進(jìn)行限制,比如限制某個(gè) IP 地址在一定時(shí)間內(nèi)只能發(fā)送特定數(shù)量的驗(yàn)證碼。同樣,也是可以被轟炸的。

至于這些機(jī)制的實(shí)現(xiàn),有機(jī)會再寫寫,你感興趣的話可以自己去操作試試!

總結(jié)

本篇文字就說了驗(yàn)證碼功能的實(shí)現(xiàn)思路和實(shí)現(xiàn),包括驗(yàn)證碼的生成、存儲、展示和校驗(yàn)。

  • 生成驗(yàn)證碼可以手寫也可以借助工具。
  • 存儲一般是存儲在 Redis 中的,當(dāng)然你想存儲在 MySQL 中也不是不可以,就是需要自己去實(shí)現(xiàn)諸如過期時(shí)間的功能。
  • 展示可以通過文本展示或者圖片展示,我們可以返回一個(gè)二進(jìn)制流給前端,前端通過 img 標(biāo)簽的 src 屬性去請求我們的接口。
  • 校驗(yàn)就拿到用戶輸入的驗(yàn)證碼,和后端生成的驗(yàn)證碼進(jìn)行比對,相同就驗(yàn)證成功,否則失敗。

最后我們也說了驗(yàn)證碼的防刷機(jī)制,這是需要考慮的,這里的防刷機(jī)制對于使用大量不同手機(jī)號、不同 IP 地址是沒效果的,依舊可以暴刷。所以這部分內(nèi)容還是有待研究的。

以上就是簡單聊聊Java中驗(yàn)證碼功能的實(shí)現(xiàn)的詳細(xì)內(nèi)容,更多關(guān)于Java驗(yàn)證碼的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 更改Maven軟件源為阿里云源的方法詳解

    更改Maven軟件源為阿里云源的方法詳解

    這篇文章主要介紹了更改Maven軟件源為阿里云源的方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-11-11
  • Redis實(shí)現(xiàn)商品秒殺功能頁面流程

    Redis實(shí)現(xiàn)商品秒殺功能頁面流程

    這篇文章主要介紹了Redis實(shí)現(xiàn)商品秒殺功能的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-09-09
  • 淺談Spring與SpringMVC父子容器的關(guān)系與初始化

    淺談Spring與SpringMVC父子容器的關(guān)系與初始化

    這篇文章主要介紹了淺談Spring與SpringMVC父子容器的關(guān)系與初始化,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • java實(shí)現(xiàn)基于UDP協(xié)議的聊天小程序操作

    java實(shí)現(xiàn)基于UDP協(xié)議的聊天小程序操作

    UDP是與TCP相對應(yīng)的協(xié)議,UDP適用于一次只傳送少量數(shù)據(jù)、對可靠性要求不高的應(yīng)用環(huán)境。正因?yàn)閁DP協(xié)議沒有連接的過程,所以它的通信效率高;但也正因?yàn)槿绱耍目煽啃圆蝗鏣CP協(xié)議高,本文給大家介紹java實(shí)現(xiàn)基于UDP協(xié)議的聊天小程序操作,感興趣的朋友一起看看吧
    2021-10-10
  • SpringBoot-Mail工具實(shí)現(xiàn)郵箱驗(yàn)證碼登錄注冊功能

    SpringBoot-Mail工具實(shí)現(xiàn)郵箱驗(yàn)證碼登錄注冊功能

    現(xiàn)在許多pc程序都有著使用郵箱驗(yàn)證碼實(shí)現(xiàn)登錄注冊的功能,那么我們應(yīng)該如何完成郵箱驗(yàn)證碼功能呢,我們可以使用springboot內(nèi)置的springboot-mail再結(jié)合redis來完成這個(gè)功能,感興趣的朋友跟隨小編一起看看吧
    2024-07-07
  • Java使用Graphics2D繪制SVG和PNG的方法

    Java使用Graphics2D繪制SVG和PNG的方法

    Java提供了許多圖形處理類和方法,如Graphics2D、AffineTransform、Stroke等,這些都可以用于繪制SVG圖像,Graphics2D是Java中用于繪制2D圖形的類,本文給大家介紹如何使用Graphics2D繪制SVG和PNG,需要的朋友可以參考下
    2023-06-06
  • 詳解JVM 運(yùn)行時(shí)內(nèi)存使用情況監(jiān)控

    詳解JVM 運(yùn)行時(shí)內(nèi)存使用情況監(jiān)控

    這篇文章主要介紹了詳解JVM 運(yùn)行時(shí)內(nèi)存使用情況監(jiān)控,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-09-09
  • 數(shù)據(jù)同步利器DataX簡介及如何使用

    數(shù)據(jù)同步利器DataX簡介及如何使用

    DataX?是阿里云?DataWorks數(shù)據(jù)集成?的開源版本,使用Java?語言編寫,在阿里巴巴集團(tuán)內(nèi)被廣泛使用的離線數(shù)據(jù)同步工具/平臺,今天給大家分享一個(gè)阿里開源的數(shù)據(jù)同步工具DataX,在Github擁有14.8k的star,非常受歡迎
    2024-02-02
  • Javaweb中使用Servlet編寫簡單的接口案例詳解

    Javaweb中使用Servlet編寫簡單的接口案例詳解

    文章介紹了如何使用Servlet編寫一個(gè)簡單的接口來校驗(yàn)用戶提交的密碼長度是否在6到12位之間,代碼分為后端部分和前端部分,給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧
    2025-02-02
  • java能寫爬蟲程序嗎

    java能寫爬蟲程序嗎

    在本篇文章里小編給大家整理的是一篇關(guān)于java是否能寫爬蟲程序的一篇文章,對此有興趣的朋友們可以學(xué)習(xí)下。
    2021-01-01

最新評論