51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

公司项目配置了 AJ-Captcha 验证码,竟然提升用户100%验证率!

公司项目配置了 AJ-Captcha 验证码,竟然提升用户100%验证率!

在当今数字化的时代,用户验证对于保障公司项目的安全性和可靠性至关重要。为了提升用户验证的效率和准确性,我们在项目中引入了 AJ-Captcha 验证码,并取得了令人瞩目的成果------用户验证率竟然提升了 100%!接下来,让我们深入探讨这一神奇转变背后的技术实现。

AJ-Captcha 行为验证码包含滑动拼图、文字点选两种方式,UI 支持弹出和嵌入两种方式。后端提供 Java 实现,前端提供了 php、angular、html、vue、uni-app、flutter、android、ios 等代码示例。

为了实现高效的数据管理,我们在项目中采用了 MyBatis-Plus 作为数据库持久框架。MyBatis-Plus 简化了数据库操作,提供了强大的 CRUD 功能和便捷的分页查询等特性,大大提高了开发效率。

运行效果:

若想获取项目完整代码以及其他文章的项目源码,且在代码编写时遇到问题需要咨询交流,欢迎加入下方的知识星球。

项目配置

首先,让我们看看项目的 pom.xml 配置。以下是添加 Anji-plus 验证码和 MyBatis-Plus 相关依赖的部分

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>3.3.2</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.icoderoad</groupId>
	<artifactId>AJ-Captcha</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>AJ-Captcha</name>
	<description>AJ-Captcha Demo project for Spring Boot</description>
&lt;properties&gt;
	&lt;java.version&gt;17&lt;/java.version&gt;
	&lt;anji-plus.version&gt;1.3.0&lt;/anji-plus.version&gt;
	&lt;mybatis-spring.version&gt;3.0.3&lt;/mybatis-spring.version&gt;
	&lt;mybatis-plus-boot-starter.version&gt;3.5.7&lt;/mybatis-plus-boot-starter.version&gt;
&lt;/properties&gt;
&lt;dependencies&gt;
	 &lt;dependency&gt;

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

	 &lt;!-- 数据库驱动依赖 --&gt;

        <dependency>             <groupId>com.mysql</groupId>             <artifactId>mysql-connector-j</artifactId>             <scope>runtime</scope>         </dependency>

	&lt;!-- Anji-plus 验证码依赖 --&gt;
     &lt;dependency&gt;

            <groupId>com.anji-plus</groupId>             <artifactId>captcha</artifactId>             <version>${anji-plus.version}</version>         </dependency>     <!-- MyBatis-Plus 依赖 -->     <dependency>         <groupId>com.baomidou</groupId>         <artifactId>mybatis-plus-boot-starter</artifactId>         <version>${mybatis-plus-boot-starter.version}</version>     </dependency>      <dependency>             <groupId>org.mybatis</groupId>             <artifactId>mybatis-spring</artifactId>             <version>${mybatis-spring.version}</version>        </dependency>     <!-- Redis 依赖 -->    <dependency>     <groupId>org.springframework.boot</groupId>     <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>

  	&lt;dependency&gt;
        &lt;groupId&gt;org.projectlombok&lt;/groupId&gt;
        &lt;artifactId&gt;lombok&lt;/artifactId&gt;
        &lt;optional&gt;true&lt;/optional&gt;
    &lt;/dependency&gt;
   	&lt;dependency&gt;
          &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
          &lt;artifactId&gt;spring-boot-starter-thymeleaf&lt;/artifactId&gt;
    &lt;/dependency&gt;
    
    &lt;!-- 其他依赖 --&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework.security&lt;/groupId&gt;
        &lt;artifactId&gt;spring-security-core&lt;/artifactId&gt;
    &lt;/dependency&gt;
 
&lt;/dependencies&gt;

&lt;build&gt;
	&lt;plugins&gt;
		&lt;plugin&gt;
			&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
			&lt;artifactId&gt;spring-boot-maven-plugin&lt;/artifactId&gt;
		&lt;/plugin&gt;
	&lt;/plugins&gt;
&lt;/build&gt;

</project>

在 yaml 属性文件中,我们进行了相关的配置:

server:
  port: 8080
# 数据库配置
spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/captcha
    username: root
    password: root
  redis:
    host: localhost
    password: 123456
    port: 6379
    
# Anji-plus 验证码配置
aj:
  captcha:
    # 缓存类型
    cache-type: redis
    # blockPuzzle 滑块 clickWord 文字点选  default默认两者都实例化
    type: blockPuzzle
    # 校验滑动拼图允许误差偏移量(默认5像素)
    slip-offset: 5
    # aes加密坐标开启或者禁用(true|false)
    aes-status: true
    # 滑动干扰项(0/1/2)
    interference-options: 0
    # 右下角水印
    water-mark: "路条编程"

数据库表设计

下面是用户表的 DDL 语句定义:

CREATE TABLE `users` (
    `id` INT PRIMARY KEY AUTO_INCREMENT,
    `username` VARCHAR(50) NOT NULL,
    `password` VARCHAR(255) NOT NULL
);

INSERT INTO users (usernamepassword)  VALUES ('admin', '$2a$10$RjHjpNXCK641apxBPd124ObuUr/MblGf4Sbegrpm8Wks/0yh7I2ve'); -- 这里假设使用 BCrypt 算法对 'admin123' 进行加密后的结果

MyBatis-Plus 相关代码实现

package com.icoderoad.AJ_Captcha.entity;

import com.baomidou.mybatisplus.annotation.TableName;

import lombok.Data;

@Data @TableName("users") public class User {     private Long id;     private String username;     private String password; }

package com.icoderoad.AJ_Captcha.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.icoderoad.AJ_Captcha.entity.User;

public interface UserMapper extends BaseMapper<User> { }

package com.icoderoad.AJ_Captcha.service;

import org.springframework.stereotype.Service;

import com.icoderoad.AJ_Captcha.entity.User;

@Service public interface UserService { User getUserByUsername(String username); }

package com.icoderoad.AJ_Captcha.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.icoderoad.AJ_Captcha.entity.User; import com.icoderoad.AJ_Captcha.mapper.UserMapper; import com.icoderoad.AJ_Captcha.service.UserService;

public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Override     public User getUserByUsername(String username) {         QueryWrapper<User> queryWrapper = new QueryWrapper<>();         queryWrapper.eq("username", username);         return this.getOne(queryWrapper);     } }

后端代码实现

package com.icoderoad.AJ_Captcha.controller;

import java.util.HashMap; import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping;

import com.icoderoad.AJ_Captcha.entity.User; import com.icoderoad.AJ_Captcha.service.UserService;

import jakarta.servlet.http.HttpServletRequest;

@Controller public class UserController {

    @Autowired     private UserService userService;

    @GetMapping("/")     public String index(Model model) {         return "index";     }

    @PostMapping("/login")     public ResponseEntity<Map<String, Boolean>> login(HttpServletRequest request) {         String username = request.getParameter("username");         String password = request.getParameter("password");

        User user = userService.getUserByUsername(username);                  boolean isAuthenticated = false;                  BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();         System.out.println(passwordEncoder.encode(password));;         if (user!= null && passwordEncoder.matches(password, user.getPassword())) {          isAuthenticated = true;         }

        Map<String, Boolean> response = new HashMap<>();         response.put("success", isAuthenticated);

        return new ResponseEntity<>(response, HttpStatus.OK);     } }

前端页面实现

在前端,我们使用 Thymeleaf 模板结合 JavaScript 和 Bootstrap 来展示和验证验证码,并实现用户名、密码和验证码的登录验证功能。以下是相关代码片段:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>验证码示例</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
    <link rel="stylesheet" type="text/css" href="/css/verify.css">
    <script src="/js/crypto-js.js"></script>
    <script src="/js/ase.js"></script>
    <script src="/js/verify.js"></script>
    <script>
        (function () {
            if (!window.Promise) {
                document.writeln('<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-promise/4.1.1/es6-promise.min.js"><' + '/' +'script>');
            }
        })();
    </script>
    <style>
    	body {
		  display: flex;
		  flex-direction: column;
		  justify-content: center;
		  align-items: center;
		  height: 100vh;
		}
	.container {
	  margin-top: -80px;
	  width: 78%;
	  display: flex;
	  flex-direction: column;
	  justify-content: center;
	  align-items: center;
	  border-radius: 10px;
	  border: 1px solid gray;
	  padding: 25px;
	}
	
	form {
		width: 80%;
	}

      .btn {             border: none;             outline: none;             width: 300px;             height: 40px;             line-height: 40px;             text-align: center;             cursor: pointer;             background-color: #409EFF;             color: #fff;             font-size: 16px;             letter-spacing: 1em;         }              </style> </head> <body>

&lt;div class=&quot;container&quot;&gt;
    &lt;h2&gt;请登录&lt;/h2&gt;
    &lt;form th:action=&quot;@{/login}&quot; method=&quot;post&quot;&gt;
        &lt;div class=&quot;form-group&quot;&gt;
            &lt;label for=&quot;username&quot;&gt;用户名&lt;/label&gt;
            &lt;input type=&quot;text&quot; class=&quot;form-control&quot; id=&quot;username&quot; name=&quot;username&quot; /&gt;
        &lt;/div&gt;
        &lt;div class=&quot;form-group&quot;&gt;
            &lt;label for=&quot;password&quot;&gt;密码&lt;/label&gt;
            &lt;input type=&quot;password&quot; class=&quot;form-control&quot; id=&quot;password&quot; name=&quot;password&quot; /&gt;
        &lt;/div&gt;
        &lt;div class=&quot;form-group&quot;&gt;
            &lt;button class=&quot;btn btn-primary&quot; id='btn' type=&quot;button&quot; &gt;登录&lt;/button&gt;
            &lt;div id=&quot;mpanel&quot; style=&quot;margin-top:50px;&quot;&gt;&lt;/div&gt;
            &lt;div id=&quot;tip&quot; style=&quot;margin-top:50px;&quot;&gt;&lt;/div&gt;
        &lt;/div&gt;
    &lt;/form&gt;
&lt;/div&gt;

&lt;script&gt;
	
      $('#mpanel').slideVerify({
          baseUrl: 'http://localhost:8080',
          mode: 'pop',
          containerId: 'btn',//pop模式 必填 被点击之后出现行为验证码的元素id
          imgSize: {
              width: '400px',
              height: '200px'
          },
          barSize: {
              width: '400px',
              height: '40px'
          },
          beforeCheck: function () {
          	var name = $(&quot;#username&quot;).val();
              var pass = $('#password').val();
              if (name === '' || pass === '') {
              	$(&quot;#tip&quot;).html('&lt;div class=&quot;alert alert-danger&quot;&gt;请输入用户名和密码!&lt;/div&gt;');
              	setTimeout(function() {
              	    $(&quot;#tip div.alert&quot;).fadeOut(500);
              	}, 5000);
                  return false;
              }
              return true;
          },
          ready: function () {},
          success: function (params) {
          	var name = $(&quot;#username&quot;).val();
              var pass = $('#password').val();
              $.ajax({
                  type: &quot;POST&quot;,
                  url: &quot;/login&quot;,
                  data: {
                      username: name,
                      password: pass
                  },
                  success: function (response) {
                      if (response.success) {
                          $(&quot;#tip&quot;).html('&lt;div class=&quot;alert alert-success&quot;&gt;登录成功&lt;/div&gt;');
                      } else {
                          $(&quot;#tip&quot;).html('&lt;div class=&quot;alert alert-danger&quot;&gt;登录失败&lt;/div&gt;');
                      }
                      setTimeout(function() {
                  	    $(&quot;#tip div.alert&quot;).fadeOut(500);
                  	}, 5000);
                  },
                  error: function () {
                      $(&quot;#tip&quot;).html('&lt;div class=&quot;alert alert-danger&quot;&gt;登录请求出错&lt;/div&gt;');
                      setTimeout(function() {
                  	    $(&quot;#tip div.alert&quot;).fadeOut(500);
                  	}, 5000);
                  }
              });
          },
          error: function () {}
      });
    
&lt;/script&gt;

</body> </html>

通过以上前后端的协同工作,我们成功地配置了 AJ-Captcha 验证码,并实现了用户名、密码和验证码的登录验证功能,显著提升了用户验证率,为公司项目的安全性和用户体验提供了有力保障。

赞(9)
未经允许不得转载:工具盒子 » 公司项目配置了 AJ-Captcha 验证码,竟然提升用户100%验证率!