添加验证码

添加依赖

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

传统web开发

前后端分离

  1. 创建验证码的配置

@Configuration
public class KaptchaConfiguration {
    @Bean
    public Producer kaptcha() {
        // 创建一个新的Properties对象,用于存储Kaptcha的配置
        Properties properties = new Properties();

        // 设置验证码图片的宽度为150像素
        properties.setProperty("kaptcha.image.width", "150");

        // 设置验证码图片的高度为50像素
        properties.setProperty("kaptcha.image.height", "50");

        // 设置验证码的字符集为数字0-9
        properties.setProperty("kaptcha.textproducer.char.string", "0123456789");

        // 设置验证码的长度为4个字符
        properties.setProperty("kaptcha.textproducer.char.length", "4");

        // 设置验证码的字体大小为40
        properties.setProperty("kaptcha.textproducer.font.size", "40");

        // 设置验证码的噪声实现类为NoNoise,即不产生噪声
        properties.setProperty("kaptcha.noise.impl", "com.google.code.kaptcha.impl.NoNoise");

        // 设置验证码的干扰实现类为ShadowGimpy,即产生一个阴影效果
        properties.setProperty("kaptcha.obscurificator.impl", "com.google.code.kaptcha.impl.ShadowGimpy");

        // 设置验证码的背景颜色从白色渐变到白色(即纯白色背景)
        properties.setProperty("kaptcha.background.clear.from", "white");
        properties.setProperty("kaptcha.background.clear.to", "white");

        // 设置验证码的字体颜色为黑色
        properties.setProperty("kaptcha.textproducer.font.color", "black");

        // 设置验证码的字符间距为5
        properties.setProperty("kaptcha.textproducer.char.space", "5");

        // 设置验证码的字体为Arial和Courier
        properties.setProperty("kaptcha.textproducer.font.names", "Arial,Courier");

        // 设置验证码的边框为无边框
        properties.setProperty("kaptcha.border", "no");

        // 设置验证码的边框颜色为黑色(实际上由于上一行设置了无边框,所以这一行设置的边框颜色不会生效)
        properties.setProperty("kaptcha.border.color", "black");

        // 创建一个DefaultKaptcha对象
        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();

        // 将上面设置的属性应用到DefaultKaptcha对象
        defaultKaptcha.setConfig(new Config(properties));

        // 返回配置好的DefaultKaptcha对象
        return defaultKaptcha;
    }
}

创建生成验证码的controller:

@Slf4j
@RestController
@RequestMapping("/")
@RequiredArgsConstructor
public class HelloController {
    private final Producer producer;

    @GetMapping("/verification-code")
    public String vc(HttpSession session) throws IOException {
        // 生成验证码
        String text = producer.createText();
        // 将验证码放入到session或者redis中
        session.setAttribute("code", text);
        // 生成图片
        BufferedImage image = producer.createImage(text);
        // 将图片转换为base64
        FastByteArrayOutputStream fastByteArrayOutputStream = new FastByteArrayOutputStream();
        ImageIO.write(image, "jpg", fastByteArrayOutputStream);
        return Base64.getEncoder().encodeToString(fastByteArrayOutputStream.toByteArray());
    }
}

LoginFilter中添加对验证码的校验逻辑:

@EqualsAndHashCode(callSuper = true)
@Data
@Slf4j
public class LoginFilter extends UsernamePasswordAuthenticationFilter {
    public static final String SPRING_SECURITY_FORM_CODE_KEY = "code";
    private String codeParameter = SPRING_SECURITY_FORM_CODE_KEY;
    @SneakyThrows
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) {
        if (!request.getMethod().equals(HttpMethod.POST.name())) {
            throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
        }
        // 仅支持json格式的数据
        if (!request.getContentType().equals(MediaType.APPLICATION_JSON_VALUE)) {
            throw new AuthenticationServiceException("Authentication contentType not supported: " + request.getContentType());
        }
        ObjectMapper objectMapper = new ObjectMapper();
        Map<String, String> map = objectMapper.readValue(request.getInputStream(), new TypeReference<>() {
        });
        // 获取请求中的验证码
        String reqCode = map.get(getCodeParameter());
        String username = map.get(getUsernameParameter());
        String password = map.get(getPasswordParameter());
        // session 验证码
        String sessionCode = (String) request.getSession().getAttribute(getCodeParameter());
        if (reqCode == null || !reqCode.equals(sessionCode)) {
            throw new AuthenticationServiceException("验证码错误");
        }

        UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
        setDetails(request, authRequest);
        return this.getAuthenticationManager().authenticate(authRequest);
    }
}

最后更新于

这有帮助吗?