7103 字
约 23 分钟
40
appendix_B
无标签

附录B 验证码模块源码详解

模块概览(面向 0 基础读者):

  • 提供图形/短信验证码生成、存储与校验接口。
  • 整合 Kaptcha、Redis 实现验证码服务的生成与分发。
  • 支持图形验证码、数字验证码等多种策略可插拔。

核心目录:

  • xuecheng-plus-checkcode/pom.xml
  • xuecheng-plus-checkcode/src/main/java/com/xuecheng/checkcode/config
  • xuecheng-plus-checkcode/src/main/java/com/xuecheng/checkcode/controller
  • xuecheng-plus-checkcode/src/main/java/com/xuecheng/checkcode/model
  • xuecheng-plus-checkcode/src/main/java/com/xuecheng/checkcode/service

文件:xuecheng-plus-checkcode/pom.xml

<?xml version="1.0" encoding="UTF-8"?> <!-- XML 声明 -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <!-- SQL 语句片段 -->
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <!-- SQL 语句片段 -->
    <modelVersion>4.0.0</modelVersion> <!-- SQL 语句片段 -->
    <parent> <!-- SQL 语句片段 -->
        <artifactId>xuecheng-plus-parent</artifactId> <!-- SQL 语句片段 -->
        <groupId>com.xuecheng</groupId> <!-- SQL 语句片段 -->
        <version>0.0.1-SNAPSHOT</version> <!-- SQL 语句片段 -->
        <relativePath>../xuecheng-plus-parent</relativePath> <!-- SQL 语句片段 -->
    </parent> <!-- SQL 语句片段 -->
    <artifactId>xuecheng-plus-checkcode</artifactId> <!-- SQL 语句片段 -->


    <dependencies> <!-- SQL 语句片段 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>com.xuecheng</groupId> <!-- SQL 语句片段 -->
            <artifactId>xuecheng-plus-base</artifactId> <!-- SQL 语句片段 -->
            <version>0.0.1-SNAPSHOT</version> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>com.alibaba.cloud</groupId> <!-- SQL 语句片段 -->
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>com.alibaba.cloud</groupId> <!-- SQL 语句片段 -->
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->

        <dependency> <!-- SQL 语句片段 -->
            <groupId>com.github.penggle</groupId> <!-- SQL 语句片段 -->
            <artifactId>kaptcha</artifactId> <!-- SQL 语句片段 -->
            <version>2.3.2</version> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <!-- Spring Boot 的 Spring Web MVC 集成 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>org.springframework.boot</groupId> <!-- SQL 语句片段 -->
            <artifactId>spring-boot-starter-web</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>org.springframework.boot</groupId> <!-- SQL 语句片段 -->
            <artifactId>spring-boot-starter-validation</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <!-- 排除 Spring Boot 依赖的日志包冲突 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>org.springframework.boot</groupId> <!-- SQL 语句片段 -->
            <artifactId>spring-boot-starter</artifactId> <!-- SQL 语句片段 -->
            <exclusions> <!-- SQL 语句片段 -->
                <exclusion> <!-- SQL 语句片段 -->
                    <groupId>org.springframework.boot</groupId> <!-- SQL 语句片段 -->
                    <artifactId>spring-boot-starter-logging</artifactId> <!-- SQL 语句片段 -->
                </exclusion> <!-- SQL 语句片段 -->
            </exclusions> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>org.springframework.boot</groupId> <!-- SQL 语句片段 -->
            <artifactId>spring-boot-starter-data-redis</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>org.apache.commons</groupId> <!-- SQL 语句片段 -->
            <artifactId>commons-pool2</artifactId> <!-- SQL 语句片段 -->
            <version>2.6.2</version> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <!-- Spring Boot 集成 Junit -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>org.springframework.boot</groupId> <!-- SQL 语句片段 -->
            <artifactId>spring-boot-starter-test</artifactId> <!-- SQL 语句片段 -->
            <scope>test</scope> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <!-- Spring Boot 集成 log4j2 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>org.springframework.boot</groupId> <!-- SQL 语句片段 -->
            <artifactId>spring-boot-starter-log4j2</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->

        <!-- Spring Boot 集成 swagger -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>com.spring4all</groupId> <!-- SQL 语句片段 -->
            <artifactId>swagger-spring-boot-starter</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>org.projectlombok</groupId> <!-- SQL 语句片段 -->
            <artifactId>lombok</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
    </dependencies> <!-- SQL 语句片段 -->

    <build> <!-- SQL 语句片段 -->
        <finalName>${project.artifactId}-${project.version}</finalName> <!-- SQL 语句片段 -->
        <plugins> <!-- SQL 语句片段 -->
            <plugin> <!-- SQL 语句片段 -->
                <groupId>org.springframework.boot</groupId> <!-- SQL 语句片段 -->
                <artifactId>spring-boot-maven-plugin</artifactId> <!-- SQL 语句片段 -->
                <version>${spring-boot.version}</version> <!-- SQL 语句片段 -->
                <executions> <!-- SQL 语句片段 -->
                    <execution> <!-- SQL 语句片段 -->
                        <goals> <!-- SQL 语句片段 -->
                            <goal>repackage</goal> <!-- SQL 语句片段 -->
                        </goals> <!-- SQL 语句片段 -->
                    </execution> <!-- SQL 语句片段 -->
                </executions> <!-- SQL 语句片段 -->
            </plugin> <!-- SQL 语句片段 -->
            <plugin> <!-- SQL 语句片段 -->
                <groupId>com.spotify</groupId> <!-- SQL 语句片段 -->
                <artifactId>docker-maven-plugin</artifactId> <!-- SQL 语句片段 -->
                <version>1.2.2</version> <!-- SQL 语句片段 -->
                <configuration> <!-- SQL 语句片段 -->
                    <!--修改imageName节点的内容,改为私有仓库地址和端口,再加上镜像id和 TAG,我们要直接传到私服-->
                    <!--配置最后生成的镜像名,docker images里的,我们这边取项目名:版本-->
                    <!--<imageName>${project.artifactId}:${project.version}</imageName>-->
                    <imageName>192.168.101.65:5000/${project.artifactId}:${project.version}</imageName> <!-- SQL 语句片段 -->
                    <!--也可以通过以下方式定义image的tag信息。 -->
                    <!-- <imageTags>
                         <imageTag>${project.version}</imageTag> <!-- SQL 语句片段 -->
                         &lt;!&ndash;build 时强制覆盖 tag,配合 imageTags 使用&ndash;&gt; <!-- SQL 语句片段 -->
                         <forceTags>true</forceTags> <!-- SQL 语句片段 -->
                         &lt;!&ndash;build 完成后,push 指定 tag 的镜像,配合 imageTags 使用&ndash;&gt; <!-- SQL 语句片段 -->
                         <pushImageTag>true</pushImageTag> <!-- SQL 语句片段 -->
                     </imageTags>--> <!-- SQL 语句片段 -->
                    <baseImage>java:8u20</baseImage> <!-- SQL 语句片段 -->
                    <maintainer>docker_maven [email protected]</maintainer> <!-- SQL 语句片段 -->
                    <workdir>/root</workdir> <!-- SQL 语句片段 -->
                    <cmd>["java", "-version"]</cmd> <!-- SQL 语句片段 -->
                    <!--来指明Dockerfile文件的所在目录,如果配置了dockerDirectory则忽略baseImage,maintainer等配置-->
                    <!--<dockerDirectory>./</dockerDirectory>-->
                    <!--2375是docker的远程端口,插件生成镜像时连接docker,这里需要指定docker远程端口-->
                    <dockerHost>http://192.168.101.65:2375</dockerHost> <!-- SQL 语句片段 -->
                    <!--入口点,project.build.finalName就是project标签下的build标签下 的filename标签内容,testDocker-->
                    <!--相当于启动容器后,会自动执行java -jar ...-->
                    <entryPoint>["java", "-Dfile.encoding=utf-8","-jar", "/root/${project.build.finalName}.jar"]</entryPoint> <!-- SQL 语句片段 -->
                    <!--是否推送到docker私有仓库,旧版本插件要配置maven的settings文件。 -->
                    <pushImage>true</pushImage> <!-- SQL 语句片段 -->
                    <registryUrl>192.168.101.65:5000</registryUrl>  <!-- 这里是复制 jar 包到 docker 容器指定目录配置 --> <!-- SQL 语句片段 -->
                    <resources> <!-- SQL 语句片段 -->
                        <resource> <!-- SQL 语句片段 -->
                            <targetPath>/root</targetPath> <!-- SQL 语句片段 -->
                            <directory>${project.build.directory}</directory> <!-- SQL 语句片段 -->
                            <!--把哪个文件上传到docker,相当于Dockerfile里的add app.jar /-->
                            <include>${project.build.finalName}.jar</include> <!-- 引用公共 SQL 片段 -->
                        </resource> <!-- SQL 语句片段 -->
                    </resources> <!-- SQL 语句片段 -->
                </configuration> <!-- SQL 语句片段 -->
            </plugin> <!-- SQL 语句片段 -->
        </plugins> <!-- SQL 语句片段 -->
    </build> <!-- SQL 语句片段 -->
</project> <!-- SQL 语句片段 -->

文件:xuecheng-plus-checkcode/src/main/java/com/xuecheng/checkcode/CheckcodeApplication.java

package com.xuecheng.checkcode; // 声明类所在的包路径

import org.springframework.boot.SpringApplication; // 导入 SpringApplication 类
import org.springframework.boot.autoconfigure.SpringBootApplication; // 导入 SpringBootApplication 类

@SpringBootApplication // 使用注解 @SpringBootApplication
public class CheckcodeApplication { // 定义 class CheckcodeApplication

    public static void main(String[] args) { // 定义方法 main(...)
        SpringApplication.run(CheckcodeApplication.class, args); // 执行语句
    } // 代码块结束

} // 代码块结束

文件:xuecheng-plus-checkcode/src/main/java/com/xuecheng/checkcode/config/KaptchaConfig.java

package com.xuecheng.checkcode.config; // 声明类所在的包路径

import com.google.code.kaptcha.impl.DefaultKaptcha; // 导入 DefaultKaptcha 类
import com.google.code.kaptcha.util.Config; // 导入 Config 类
import org.springframework.context.annotation.Bean; // 导入 Bean 类
import org.springframework.context.annotation.Configuration; // 导入 Configuration 类

import java.util.Properties; // 导入 Properties 类

/** // 保留原作者写的块注释
 * Kaptcha图片验证码配置类 // 保留原作者写的块注释
 * @author 攀博课堂(www.pbteach.com) // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 **/ // 保留原作者写的块注释
@Configuration // 使用注解 @Configuration
public class KaptchaConfig { // 定义 class KaptchaConfig

    //图片验证码生成器,使用开源的kaptcha // 保留原作者写的行内注释
    @Bean // 使用注解 @Bean
    public DefaultKaptcha producer() { // 定义方法 producer(...)
        Properties properties = new Properties(); // 创建 Properties 对象并赋值给 properties
        properties.put("kaptcha.border", "no"); // 执行语句
        properties.put("kaptcha.textproducer.font.color", "black"); // 执行语句
        properties.put("kaptcha.textproducer.char.space", "10"); // 执行语句
        properties.put("kaptcha.textproducer.char.length","4"); // 执行语句
        properties.put("kaptcha.image.height","34"); // 执行语句
        properties.put("kaptcha.image.width","138"); // 执行语句
        properties.put("kaptcha.textproducer.font.size","25"); // 执行语句

        properties.put("kaptcha.noise.impl","com.google.code.kaptcha.impl.NoNoise"); // 执行语句
        Config config = new Config(properties); // 创建 Config 对象并赋值给 config
        DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); // 创建 DefaultKaptcha 对象并赋值给 defaultKaptcha
        defaultKaptcha.setConfig(config); // 执行语句
        return defaultKaptcha; // 返回 defaultKaptcha
    } // 代码块结束
} // 代码块结束

文件:xuecheng-plus-checkcode/src/main/java/com/xuecheng/checkcode/controller/CheckCodeController.java

package com.xuecheng.checkcode.controller; // 声明类所在的包路径

import com.xuecheng.base.model.RestResponse; // 导入 RestResponse 类
import com.xuecheng.checkcode.model.CheckCodeParamsDto; // 导入 CheckCodeParamsDto 类
import com.xuecheng.checkcode.model.CheckCodeResultDto; // 导入 CheckCodeResultDto 类
import com.xuecheng.checkcode.service.CheckCodeService; // 导入 CheckCodeService 类
import io.swagger.annotations.Api; // 导入 Api 类
import io.swagger.annotations.ApiImplicitParam; // 导入 ApiImplicitParam 类
import io.swagger.annotations.ApiImplicitParams; // 导入 ApiImplicitParams 类
import io.swagger.annotations.ApiOperation; // 导入 ApiOperation 类
import org.springframework.beans.factory.annotation.Autowired; // 导入 Autowired 类
import org.springframework.web.bind.annotation.*; // 导入 * 类

import javax.annotation.Resource; // 导入 Resource 类
import java.util.Map; // 导入 Map 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description 验证码服务接口 // 保留原作者写的块注释
 * @date 2022/9/29 18:39 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Api(value = "验证码服务接口") // 使用注解 @Api(value = "验证码服务接口")
@RestController // 使用注解 @RestController
public class CheckCodeController { // 定义 class CheckCodeController

    @Resource(name = "PicCheckCodeService") // 使用注解 @Resource(name = "PicCheckCodeService")
    private CheckCodeService picCheckCodeService; // 执行语句


    @ApiOperation(value="生成验证信息", notes="生成验证信息") // 使用注解 @ApiOperation(value="生成验证信息", notes="生成验证信息")
    @PostMapping(value = "/pic") // 使用注解 @PostMapping(value = "/pic")
    public CheckCodeResultDto generatePicCheckCode(CheckCodeParamsDto checkCodeParamsDto){ // 定义方法 generatePicCheckCode(...)
        return picCheckCodeService.generate(checkCodeParamsDto); // 返回 picCheckCodeService.generate(checkCodeParamsDto)
    } // 代码块结束

    @ApiOperation(value="校验", notes="校验") // 使用注解 @ApiOperation(value="校验", notes="校验")
    @ApiImplicitParams({ // 使用注解 @ApiImplicitParams({
            @ApiImplicitParam(name = "name", value = "业务名称", required = true, dataType = "String", paramType="query"), // 使用注解 @ApiImplicitParam(name = "name", value = "业务名称", required = true, dataType = "String", paramType="query"),
            @ApiImplicitParam(name = "key", value = "验证key", required = true, dataType = "String", paramType="query"), // 使用注解 @ApiImplicitParam(name = "key", value = "验证key", required = true, dataType = "String", paramType="query"),
            @ApiImplicitParam(name = "code", value = "验证码", required = true, dataType = "String", paramType="query") // 使用注解 @ApiImplicitParam(name = "code", value = "验证码", required = true, dataType = "String", paramType="query")
    }) // 代码逻辑
    @PostMapping(value = "/verify") // 使用注解 @PostMapping(value = "/verify")
    public Boolean verify(String key, String code){ // 定义方法 verify(...)
        Boolean isSuccess = picCheckCodeService.verify(key,code); // 把 picCheckCodeService.verify(key,code) 赋值给 isSuccess
        return isSuccess; // 返回 isSuccess
    } // 代码块结束
} // 代码块结束

文件:xuecheng-plus-checkcode/src/main/java/com/xuecheng/checkcode/model/CheckCodeParamsDto.java

package com.xuecheng.checkcode.model; // 声明类所在的包路径

import lombok.Data; // 导入 Data 类

import java.util.Map; // 导入 Map 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description 验证码生成参数类 // 保留原作者写的块注释
 * @date 2022/9/29 15:48 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Data // 使用注解 @Data
public class CheckCodeParamsDto { // 定义 class CheckCodeParamsDto

    /** // 保留原作者写的块注释
     * 验证码类型:pic、sms、email等 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String checkCodeType; // 执行语句

    /** // 保留原作者写的块注释
     * 业务携带参数 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String param1; // 执行语句
    private String param2; // 执行语句
    private String param3; // 执行语句
} // 代码块结束

文件:xuecheng-plus-checkcode/src/main/java/com/xuecheng/checkcode/model/CheckCodeResultDto.java

package com.xuecheng.checkcode.model; // 声明类所在的包路径

import lombok.Data; // 导入 Data 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description 验证码生成结果类 // 保留原作者写的块注释
 * @date 2022/9/29 15:48 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Data // 使用注解 @Data
public class CheckCodeResultDto { // 定义 class CheckCodeResultDto

    /** // 保留原作者写的块注释
     * key用于验证 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String key; // 执行语句

    /** // 保留原作者写的块注释
     * 混淆后的内容 // 保留原作者写的块注释
     * 举例: // 保留原作者写的块注释
     * 1.图片验证码为:图片base64编码 // 保留原作者写的块注释
     * 2.短信验证码为:null // 保留原作者写的块注释
     * 3.邮件验证码为: null // 保留原作者写的块注释
     * 4.邮件链接点击验证为:null // 保留原作者写的块注释
     * ... // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String aliasing; // 执行语句
} // 代码块结束

文件:xuecheng-plus-checkcode/src/main/java/com/xuecheng/checkcode/service/AbstractCheckCodeService.java

package com.xuecheng.checkcode.service; // 声明类所在的包路径

import com.xuecheng.checkcode.model.CheckCodeParamsDto; // 导入 CheckCodeParamsDto 类
import com.xuecheng.checkcode.model.CheckCodeResultDto; // 导入 CheckCodeResultDto 类
import lombok.Data; // 导入 Data 类
import lombok.extern.slf4j.Slf4j; // 导入 Slf4j 类
import org.apache.commons.lang.StringUtils; // 导入 StringUtils 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description 验证码接口 // 保留原作者写的块注释
 * @date 2022/9/29 15:59 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Slf4j // 使用注解 @Slf4j
public abstract class AbstractCheckCodeService implements CheckCodeService { // 代码逻辑

    protected CheckCodeGenerator checkCodeGenerator; // 执行语句
    protected KeyGenerator keyGenerator; // 执行语句
    protected CheckCodeStore checkCodeStore; // 执行语句

    public abstract void  setCheckCodeGenerator(CheckCodeGenerator checkCodeGenerator); // 执行语句
    public abstract void  setKeyGenerator(KeyGenerator keyGenerator); // 执行语句
    public abstract void  setCheckCodeStore(CheckCodeStore CheckCodeStore); // 执行语句


    /** // 保留原作者写的块注释
     * @description 生成验证公用方法 // 保留原作者写的块注释
     * @param checkCodeParamsDto 生成验证码参数 // 保留原作者写的块注释
     * @param code_length 验证码长度 // 保留原作者写的块注释
     * @param keyPrefix key的前缀 // 保留原作者写的块注释
     * @param expire 过期时间 // 保留原作者写的块注释
     * @return com.xuecheng.checkcode.service.AbstractCheckCodeService.GenerateResult 生成结果 // 保留原作者写的块注释
     * @author Mr.M // 保留原作者写的块注释
     * @date 2022/9/30 6:07 // 保留原作者写的块注释
    */ // 保留原作者写的块注释
    public GenerateResult generate(CheckCodeParamsDto checkCodeParamsDto,Integer code_length,String keyPrefix,Integer expire){ // 定义方法 generate(...)
        //生成四位验证码 // 保留原作者写的行内注释
        String code = checkCodeGenerator.generate(code_length); // 把 checkCodeGenerator.generate(code_length) 赋值给 code
        log.debug("生成验证码:{}",code); // 执行语句
        //生成一个key // 保留原作者写的行内注释
        String key = keyGenerator.generate(keyPrefix); // 把 keyGenerator.generate(keyPrefix) 赋值给 key

        //存储验证码 // 保留原作者写的行内注释
        checkCodeStore.set(key,code,expire); // 执行语句
        //返回验证码生成结果 // 保留原作者写的行内注释
        GenerateResult generateResult = new GenerateResult(); // 创建 GenerateResult 对象并赋值给 generateResult
        generateResult.setKey(key); // 执行语句
        generateResult.setCode(code); // 执行语句
        return generateResult; // 返回 generateResult
    } // 代码块结束

    @Data // 使用注解 @Data
    protected class GenerateResult{ // 定义 class GenerateResult{
        String key; // 执行语句
        String code; // 执行语句
    } // 代码块结束


    public abstract CheckCodeResultDto generate(CheckCodeParamsDto checkCodeParamsDto); // 执行语句


    public boolean verify(String key, String code){ // 定义方法 verify(...)
        if (StringUtils.isBlank(key) || StringUtils.isBlank(code)){ // 定义方法 方法(...)
            return false; // 返回 false
        } // 代码块结束
        String code_l = checkCodeStore.get(key); // 把 checkCodeStore.get(key) 赋值给 code_l
        if (code_l == null){ // 定义方法 方法(...)
            return false; // 返回 false
        } // 代码块结束
        boolean result = code_l.equalsIgnoreCase(code); // 把 code_l.equalsIgnoreCase(code) 赋值给 result
        if(result){ // 定义方法 方法(...)
            //删除验证码 // 保留原作者写的行内注释
            checkCodeStore.remove(key); // 执行语句
        } // 代码块结束
        return result; // 返回 result
    } // 代码块结束


} // 代码块结束

文件:xuecheng-plus-checkcode/src/main/java/com/xuecheng/checkcode/service/CheckCodeService.java

package com.xuecheng.checkcode.service; // 声明类所在的包路径

import com.xuecheng.checkcode.model.CheckCodeParamsDto; // 导入 CheckCodeParamsDto 类
import com.xuecheng.checkcode.model.CheckCodeResultDto; // 导入 CheckCodeResultDto 类
import org.springframework.beans.factory.annotation.Autowired; // 导入 Autowired 类

import javax.annotation.Resource; // 导入 Resource 类
import java.util.Map; // 导入 Map 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description 验证码接口 // 保留原作者写的块注释
 * @date 2022/9/29 15:59 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
public interface CheckCodeService { // 定义 interface CheckCodeService


    /** // 保留原作者写的块注释
     * @description 生成验证码 // 保留原作者写的块注释
     * @param checkCodeParamsDto 生成验证码参数 // 保留原作者写的块注释
     * @return com.xuecheng.checkcode.model.CheckCodeResultDto 验证码结果 // 保留原作者写的块注释
     * @author Mr.M // 保留原作者写的块注释
     * @date 2022/9/29 18:21 // 保留原作者写的块注释
    */ // 保留原作者写的块注释
     CheckCodeResultDto generate(CheckCodeParamsDto checkCodeParamsDto); // 执行语句

     /** // 保留原作者写的块注释
      * @description 校验验证码 // 保留原作者写的块注释
      * @param key // 保留原作者写的块注释
      * @param code // 保留原作者写的块注释
      * @return boolean // 保留原作者写的块注释
      * @author Mr.M // 保留原作者写的块注释
      * @date 2022/9/29 18:46 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    public boolean verify(String key, String code); // 执行语句


    /** // 保留原作者写的块注释
     * @description 验证码生成器 // 保留原作者写的块注释
     * @author Mr.M // 保留原作者写的块注释
     * @date 2022/9/29 16:34 // 保留原作者写的块注释
    */ // 保留原作者写的块注释
    public interface CheckCodeGenerator{ // 定义 interface CheckCodeGenerator{
        /** // 保留原作者写的块注释
         * 验证码生成 // 保留原作者写的块注释
         * @return 验证码 // 保留原作者写的块注释
         */ // 保留原作者写的块注释
        String generate(int length); // 执行语句
        

    } // 代码块结束

    /** // 保留原作者写的块注释
     * @description key生成器 // 保留原作者写的块注释
     * @author Mr.M // 保留原作者写的块注释
     * @date 2022/9/29 16:34 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    public interface KeyGenerator{ // 定义 interface KeyGenerator{

        /** // 保留原作者写的块注释
         * key生成 // 保留原作者写的块注释
         * @return 验证码 // 保留原作者写的块注释
         */ // 保留原作者写的块注释
        String generate(String prefix); // 执行语句
    } // 代码块结束


    /** // 保留原作者写的块注释
     * @description 验证码存储 // 保留原作者写的块注释
     * @author Mr.M // 保留原作者写的块注释
     * @date 2022/9/29 16:34 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    public interface CheckCodeStore{ // 定义 interface CheckCodeStore{

        /** // 保留原作者写的块注释
         * @description 向缓存设置key // 保留原作者写的块注释
         * @param key key // 保留原作者写的块注释
         * @param value value // 保留原作者写的块注释
         * @param expire 过期时间,单位秒 // 保留原作者写的块注释
         * @return void // 保留原作者写的块注释
         * @author Mr.M // 保留原作者写的块注释
         * @date 2022/9/29 17:15 // 保留原作者写的块注释
        */ // 保留原作者写的块注释
        void set(String key, String value, Integer expire); // 执行语句

        String get(String key); // 执行语句

        void remove(String key); // 执行语句
    } // 代码块结束
} // 代码块结束

文件:xuecheng-plus-checkcode/src/main/java/com/xuecheng/checkcode/service/impl/MemoryCheckCodeStore.java

package com.xuecheng.checkcode.service.impl; // 声明类所在的包路径

import com.xuecheng.checkcode.service.CheckCodeService; // 导入 CheckCodeService 类
import org.springframework.beans.factory.annotation.Autowired; // 导入 Autowired 类
import org.springframework.stereotype.Component; // 导入 Component 类

import java.util.HashMap; // 导入 HashMap 类
import java.util.Map; // 导入 Map 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description 使用本地内存存储验证码,测试用 // 保留原作者写的块注释
 * @date 2022/9/29 18:36 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Component("MemoryCheckCodeStore") // 使用注解 @Component("MemoryCheckCodeStore")
public class MemoryCheckCodeStore implements CheckCodeService.CheckCodeStore { // 定义 class MemoryCheckCodeStore

    Map<String,String> map = new HashMap<String,String>(); // 创建 HashMap<String,String> 对象并赋值给 map

    @Override // 使用注解 @Override
    public void set(String key, String value, Integer expire) { // 定义方法 set(...)
        map.put(key,value); // 执行语句
    } // 代码块结束

    @Override // 使用注解 @Override
    public String get(String key) { // 定义方法 get(...)
        return map.get(key); // 返回 map.get(key)
    } // 代码块结束

    @Override // 使用注解 @Override
    public void remove(String key) { // 定义方法 remove(...)
        map.remove(key); // 执行语句
    } // 代码块结束
} // 代码块结束

文件:xuecheng-plus-checkcode/src/main/java/com/xuecheng/checkcode/service/impl/NumberLetterCheckCodeGenerator.java

package com.xuecheng.checkcode.service.impl; // 声明类所在的包路径

import com.xuecheng.checkcode.model.CheckCodeParamsDto; // 导入 CheckCodeParamsDto 类
import com.xuecheng.checkcode.service.CheckCodeService; // 导入 CheckCodeService 类
import org.springframework.stereotype.Component; // 导入 Component 类

import java.util.Random; // 导入 Random 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description 数字字母生成器 // 保留原作者写的块注释
 * @date 2022/9/29 18:28 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Component("NumberLetterCheckCodeGenerator") // 使用注解 @Component("NumberLetterCheckCodeGenerator")
public class NumberLetterCheckCodeGenerator implements CheckCodeService.CheckCodeGenerator { // 定义 class NumberLetterCheckCodeGenerator


    @Override // 使用注解 @Override
    public String generate(int length) { // 定义方法 generate(...)
        String str="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; // 把 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" 赋值给 str
        Random random=new Random(); // 创建 Random 对象并赋值给 random
        StringBuffer sb=new StringBuffer(); // 创建 StringBuffer 对象并赋值给 sb
        for(int i=0;i<length;i++){ // 定义方法 方法(...)
            int number=random.nextInt(36); // 把 random.nextInt(36) 赋值给 number
            sb.append(str.charAt(number)); // 执行语句
        } // 代码块结束
        return sb.toString(); // 返回 sb.toString()
    } // 代码块结束


} // 代码块结束

文件:xuecheng-plus-checkcode/src/main/java/com/xuecheng/checkcode/service/impl/PicCheckCodeServiceImpl.java

package com.xuecheng.checkcode.service.impl; // 声明类所在的包路径

import com.google.code.kaptcha.impl.DefaultKaptcha; // 导入 DefaultKaptcha 类
import com.xuecheng.base.utils.EncryptUtil; // 导入 EncryptUtil 类
import com.xuecheng.checkcode.model.CheckCodeParamsDto; // 导入 CheckCodeParamsDto 类
import com.xuecheng.checkcode.model.CheckCodeResultDto; // 导入 CheckCodeResultDto 类
import com.xuecheng.checkcode.service.AbstractCheckCodeService; // 导入 AbstractCheckCodeService 类
import com.xuecheng.checkcode.service.CheckCodeService; // 导入 CheckCodeService 类
import org.springframework.beans.factory.annotation.Autowired; // 导入 Autowired 类
import org.springframework.stereotype.Service; // 导入 Service 类
import sun.misc.BASE64Encoder; // 导入 BASE64Encoder 类

import javax.annotation.Resource; // 导入 Resource 类
import javax.imageio.ImageIO; // 导入 ImageIO 类
import java.awt.image.BufferedImage; // 导入 BufferedImage 类
import java.io.ByteArrayOutputStream; // 导入 ByteArrayOutputStream 类
import java.io.IOException; // 导入 IOException 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description 图片验证码生成器 // 保留原作者写的块注释
 * @date 2022/9/29 16:16 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Service("PicCheckCodeService") // 使用注解 @Service("PicCheckCodeService")
public class PicCheckCodeServiceImpl extends AbstractCheckCodeService implements CheckCodeService { // 定义 class PicCheckCodeServiceImpl


    @Autowired // 使用注解 @Autowired
    private DefaultKaptcha kaptcha; // 执行语句

    @Resource(name="NumberLetterCheckCodeGenerator") // 使用注解 @Resource(name="NumberLetterCheckCodeGenerator")
    @Override // 使用注解 @Override
    public void setCheckCodeGenerator(CheckCodeGenerator checkCodeGenerator) { // 定义方法 setCheckCodeGenerator(...)
        this.checkCodeGenerator = checkCodeGenerator; // 把 checkCodeGenerator 赋值给 this.checkCodeGenerator
    } // 代码块结束

    @Resource(name="UUIDKeyGenerator") // 使用注解 @Resource(name="UUIDKeyGenerator")
    @Override // 使用注解 @Override
    public void setKeyGenerator(KeyGenerator keyGenerator) { // 定义方法 setKeyGenerator(...)
        this.keyGenerator = keyGenerator; // 把 keyGenerator 赋值给 this.keyGenerator
    } // 代码块结束


    @Resource(name="RedisCheckCodeStore") // 使用注解 @Resource(name="RedisCheckCodeStore")
    @Override // 使用注解 @Override
    public void setCheckCodeStore(CheckCodeStore checkCodeStore) { // 定义方法 setCheckCodeStore(...)
        this.checkCodeStore = checkCodeStore; // 把 checkCodeStore 赋值给 this.checkCodeStore
    } // 代码块结束


    @Override // 使用注解 @Override
    public CheckCodeResultDto generate(CheckCodeParamsDto checkCodeParamsDto) { // 定义方法 generate(...)
        GenerateResult generate = generate(checkCodeParamsDto, 4, "checkcode:", 300); // 把 generate(checkCodeParamsDto, 4, "checkcode:", 300) 赋值给 generate
        String key = generate.getKey(); // 把 generate.getKey() 的返回值赋给 key
        String code = generate.getCode(); // 把 generate.getCode() 的返回值赋给 code
        String pic = createPic(code); // 把 createPic(code) 赋值给 pic
        CheckCodeResultDto checkCodeResultDto = new CheckCodeResultDto(); // 创建 CheckCodeResultDto 对象并赋值给 checkCodeResultDto
        checkCodeResultDto.setAliasing(pic); // 执行语句
        checkCodeResultDto.setKey(key); // 执行语句
        return checkCodeResultDto; // 返回 checkCodeResultDto

    } // 代码块结束

    private String createPic(String code) { // 定义方法 createPic(...)
        // 生成图片验证码 // 保留原作者写的行内注释
        ByteArrayOutputStream outputStream = null; // 把变量 outputStream 初始化为 null
        BufferedImage image = kaptcha.createImage(code); // 把 kaptcha.createImage(code) 赋值给 image

        outputStream = new ByteArrayOutputStream(); // 创建 ByteArrayOutputStream 对象并赋值给 outputStream
        String imgBase64Encoder = null; // 把变量 imgBase64Encoder 初始化为 null
        try { // 尝试执行可能抛出异常的代码
            // 对字节数组Base64编码 // 保留原作者写的行内注释
            BASE64Encoder base64Encoder = new BASE64Encoder(); // 创建 BASE64Encoder 对象并赋值给 base64Encoder
            ImageIO.write(image, "png", outputStream); // 执行语句
            imgBase64Encoder = "data:image/png;base64," + EncryptUtil.encodeBase64(outputStream.toByteArray()); // 把 "data:image/png;base64," + EncryptUtil.encodeBase64(outputStream.toByteArray()) 赋值给 imgBase64Encoder
        } catch (IOException e) { // 定义方法 catch(...)
            e.printStackTrace(); // 执行语句
        } finally { // 代码逻辑
            try { // 尝试执行可能抛出异常的代码
                outputStream.close(); // 执行语句
            } catch (IOException e) { // 定义方法 catch(...)
                e.printStackTrace(); // 执行语句
            } // 代码块结束
        } // 代码块结束
        return imgBase64Encoder; // 返回 imgBase64Encoder
    } // 代码块结束
} // 代码块结束

文件:xuecheng-plus-checkcode/src/main/java/com/xuecheng/checkcode/service/impl/RedisCheckCodeStore.java

package com.xuecheng.checkcode.service.impl; // 声明类所在的包路径

import com.xuecheng.checkcode.service.CheckCodeService; // 导入 CheckCodeService 类
import org.springframework.beans.factory.annotation.Autowired; // 导入 Autowired 类
import org.springframework.data.redis.core.RedisTemplate; // 导入 RedisTemplate 类
import org.springframework.stereotype.Component; // 导入 Component 类

import java.util.HashMap; // 导入 HashMap 类
import java.util.Map; // 导入 Map 类
import java.util.concurrent.TimeUnit; // 导入 TimeUnit 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description 使用redis存储验证码,测试用 // 保留原作者写的块注释
 * @date 2022/9/29 18:36 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Component("RedisCheckCodeStore") // 使用注解 @Component("RedisCheckCodeStore")
public class RedisCheckCodeStore implements CheckCodeService.CheckCodeStore { // 定义 class RedisCheckCodeStore

    @Autowired // 使用注解 @Autowired
    RedisTemplate redisTemplate; // 执行语句


    @Override // 使用注解 @Override
    public void set(String key, String value, Integer expire) { // 定义方法 set(...)
        redisTemplate.opsForValue().set(key,value,expire, TimeUnit.SECONDS); // 执行语句
    } // 代码块结束

    @Override // 使用注解 @Override
    public String get(String key) { // 定义方法 get(...)
        return (String) redisTemplate.opsForValue().get(key); // 返回 (String) redisTemplate.opsForValue().get(key)
    } // 代码块结束

    @Override // 使用注解 @Override
    public void remove(String key) { // 定义方法 remove(...)
        redisTemplate.delete(key); // 执行语句
    } // 代码块结束
} // 代码块结束

文件:xuecheng-plus-checkcode/src/main/java/com/xuecheng/checkcode/service/impl/UUIDKeyGenerator.java

package com.xuecheng.checkcode.service.impl; // 声明类所在的包路径

import com.xuecheng.checkcode.service.CheckCodeService; // 导入 CheckCodeService 类
import org.springframework.stereotype.Component; // 导入 Component 类

import java.util.UUID; // 导入 UUID 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description uuid生成器 // 保留原作者写的块注释
 * @date 2022/9/29 16:16 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Component("UUIDKeyGenerator") // 使用注解 @Component("UUIDKeyGenerator")
public class UUIDKeyGenerator implements CheckCodeService.KeyGenerator { // 定义 class UUIDKeyGenerator
    @Override // 使用注解 @Override
    public String generate(String prefix) { // 定义方法 generate(...)
        String uuid = UUID.randomUUID().toString(); // 把 UUID.randomUUID().toString() 的返回值赋给 uuid
        return prefix + uuid.replaceAll("-", ""); // 返回 prefix + uuid.replaceAll("-", "")
    } // 代码块结束
} // 代码块结束

文件:xuecheng-plus-checkcode/src/main/resources/bootstrap.yml

spring:
  application:
    name: checkcode
  cloud:
    nacos:
      server-addr: 192.168.101.65:8848
      discovery:
        namespace: dev402
        group: xuecheng-plus-project
      config:
        namespace: dev402
        group: xuecheng-plus-project
        file-extension: yaml
        refresh-enabled: true
        shared-configs:
          - data-id: swagger-${spring.profiles.active}.yaml
            group: xuecheng-plus-common
            refresh: true
          - data-id: logging-${spring.profiles.active}.yaml
            group: xuecheng-plus-common
            refresh: true
          - data-id: redis-${spring.profiles.active}.yaml
            group: xuecheng-plus-common
            refresh: true

  profiles:
    active: dev

文件:xuecheng-plus-checkcode/src/main/resources/log4j2-dev.xml

<?xml version="1.0" encoding="UTF-8"?> <!-- XML 声明 -->
<Configuration monitorInterval="180" packages=""> <!-- SQL 语句片段 -->
    <properties> <!-- SQL 语句片段 -->
        <property name="logdir">logs</property> <!-- SQL 语句片段 -->
        <property name="PATTERN">%date{YYYY-MM-dd HH:mm:ss,SSS} %level [%thread][%file:%line] - %msg%n%throwable</property> <!-- SQL 语句片段 -->
    </properties> <!-- SQL 语句片段 -->
    <Appenders> <!-- SQL 语句片段 -->
        <Console name="Console" target="SYSTEM_OUT"> <!-- SQL 语句片段 -->
            <PatternLayout pattern="${PATTERN}"/> <!-- SQL 语句片段 -->
        </Console> <!-- SQL 语句片段 -->

        <RollingFile name="ErrorAppender" fileName="${logdir}/error.log" <!-- SQL 语句片段 -->
            filePattern="${logdir}/$${date:yyyy-MM-dd}/error.%d{yyyy-MM-dd-HH}.log" append="true"> <!-- SQL 语句片段 -->
            <PatternLayout pattern="${PATTERN}"/> <!-- SQL 语句片段 -->
            <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/> <!-- SQL 语句片段 -->
            <Policies> <!-- SQL 语句片段 -->
                <TimeBasedTriggeringPolicy interval="1" modulate="true" /> <!-- SQL 语句片段 -->
            </Policies> <!-- SQL 语句片段 -->
        </RollingFile> <!-- SQL 语句片段 -->

        <RollingFile name="DebugAppender" fileName="${logdir}/info.log" <!-- SQL 语句片段 -->
            filePattern="${logdir}/$${date:yyyy-MM-dd}/info.%d{yyyy-MM-dd-HH}.log" append="true"> <!-- SQL 语句片段 -->
            <PatternLayout pattern="${PATTERN}"/> <!-- SQL 语句片段 -->
            <ThresholdFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY"/> <!-- SQL 语句片段 -->
            <Policies> <!-- SQL 语句片段 -->
                <TimeBasedTriggeringPolicy interval="1" modulate="true" /> <!-- SQL 语句片段 -->
            </Policies> <!-- SQL 语句片段 -->
        </RollingFile> <!-- SQL 语句片段 -->
        
        <!--异步appender-->
         <Async name="AsyncAppender" includeLocation="true"> <!-- SQL 语句片段 -->
            <AppenderRef ref="ErrorAppender"/> <!-- SQL 语句片段 -->
            <AppenderRef ref="DebugAppender"/> <!-- SQL 语句片段 -->
        </Async> <!-- SQL 语句片段 -->
    </Appenders> <!-- SQL 语句片段 -->
    
    <Loggers> <!-- SQL 语句片段 -->
         <!--过滤掉spring和mybatis的一些无用的debug信息-->
        <logger name="org.springframework" level="INFO"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->
        <logger name="org.mybatis" level="INFO"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->
        <logger name="cn.itcast.wanxinp2p.consumer.mapper" level="DEBUG"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->

        <logger name="springfox" level="INFO"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->
		<logger name="org.apache.http" level="INFO"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->
        <logger name="com.netflix.discovery" level="INFO"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->
        
        <logger name="RocketmqCommon"  level="INFO" > <!-- SQL 语句片段 -->
		</logger> <!-- SQL 语句片段 -->
		
		<logger name="RocketmqRemoting" level="INFO"  > <!-- SQL 语句片段 -->
		</logger> <!-- SQL 语句片段 -->
		
		<logger name="RocketmqClient" level="WARN"> <!-- SQL 语句片段 -->
		</logger> <!-- SQL 语句片段 -->

        <logger name="org.dromara.hmily" level="WARN"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->

        <logger name="org.dromara.hmily.lottery" level="WARN"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->

        <logger name="org.dromara.hmily.bonuspoint" level="WARN"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->
		
        <!--OFF   0-->
        <!--FATAL   100-->
        <!--ERROR   200-->
        <!--WARN   300-->
        <!--INFO   400-->
        <!--DEBUG   500-->
        <!--TRACE   600-->
        <!--ALL   Integer.MAX_VALUE-->
        <Root level="DEBUG" includeLocation="true"> <!-- SQL 语句片段 -->
            <AppenderRef ref="AsyncAppender"/> <!-- SQL 语句片段 -->
            <AppenderRef ref="Console"/> <!-- SQL 语句片段 -->
            <AppenderRef ref="DebugAppender"/> <!-- SQL 语句片段 -->
        </Root> <!-- SQL 语句片段 -->
    </Loggers> <!-- SQL 语句片段 -->
</Configuration> <!-- SQL 语句片段 -->

文件:xuecheng-plus-checkcode/src/test/java/com/xuecheng/checkcode/XuechengPlusCheckcodeApplicationTests.java

package com.xuecheng.checkcode; // 声明类所在的包路径

import org.junit.jupiter.api.Test; // 导入 Test 类
import org.springframework.boot.test.context.SpringBootTest; // 导入 SpringBootTest 类

@SpringBootTest // 使用注解 @SpringBootTest
class XuechengPlusCheckcodeApplicationTests { // 定义 class XuechengPlusCheckcodeApplicationTests

    @Test // 使用注解 @Test
    void contextLoads() { // 定义方法 contextLoads(...)
    } // 代码块结束

} // 代码块结束
appendix_B
https://clxhxhhr.top/posts/4369/
作者
clxstart
发布于
2026-09-26
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。