springboot登陆页面图片验证码简单的web项目实现

yizhihongxing

下面我来详细讲解“springboot登陆页面图片验证码简单的web项目实现”的完整攻略。

简介

本项目是一个基于Spring Boot框架的简单web项目,使用图片验证码来保护用户登录页面,防范恶意攻击和爆破。

实现步骤

第一步:新建Spring Boot项目

首先,我们需要新建一个Spring Boot项目,以便进行后续的开发。在创建项目时需要注意选择Web和Thymeleaf模板引擎。

第二步:添加验证码相关依赖

pom.xml文件中添加以下依赖:

<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-core</artifactId>
    <version>3.10.2</version>
</dependency>
<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-dysmsapi</artifactId>
    <version>1.0.0</version>
</dependency>

这里我们使用了阿里云提供的短信验证码服务。

第三步:编写验证码生成类

新建一个VerifyCodeUtils类,用于生成随机验证码图片,并将验证码保存在Session中。
代码示例:

public class VerifyCodeUtils {
    private static final String VERIFY_CODES = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

    /**
     * 生成随机验证码图片,并将验证码存储在session中
     *
     * @param width    图片宽度
     * @param height   图片高度
     * @param request  HttpServletRequest对象
     * @param response HttpServletResponse对象
     * @param length   验证码长度
     * @throws IOException
     */
    public static void generateImage(int width, int height, HttpServletRequest request, HttpServletResponse response, int length) throws IOException {
        String verifyCode = generateVerifyCode(length);

        // 将验证码存储在Session中
        HttpSession session = request.getSession();
        session.setAttribute("verifyCode", verifyCode);

        response.setContentType("image/jpeg");

        //禁止图片缓存
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", -1);

        OutputStream out = response.getOutputStream();
        BufferedImage image = createImage(width, height, verifyCode);
        ImageIO.write(image, "JPEG", out);
        out.flush();
        out.close();
    }

    /**
     * 生成随机验证码
     *
     * @param length 验证码长度
     * @return 验证码字符串
     */
    public static String generateVerifyCode(int length) {
        StringBuilder sb = new StringBuilder(length);
        for (int i = 0; i < length; i++) {
            sb.append(VERIFY_CODES.charAt(new Random().nextInt(VERIFY_CODES.length())));
        }
        return sb.toString();
    }

    /**
     * 创建验证码图片
     *
     * @param width        图片宽度
     * @param height       图片高度
     * @param verifyCode   验证码字符串
     * @return BufferedImage对象
     */
    public static BufferedImage createImage(int width, int height, String verifyCode) {
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics g = image.getGraphics();

        // 绘制背景
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, width, height);

        // 绘制干扰线
        Random r = new Random();
        for (int i = 0; i < 10; i++) {
            g.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255)));
            int x1 = r.nextInt(width);
            int y1 = r.nextInt(height);
            int x2 = r.nextInt(width);
            int y2 = r.nextInt(height);
            g.drawLine(x1, y1, x2, y2);
        }

        // 绘制验证码
        Font font = new Font("Arial", Font.BOLD, height - 4);
        g.setFont(font);
        for (int i = 0; i < verifyCode.length(); i++) {
            char c = verifyCode.charAt(i);
            g.setColor(new Color(r.nextInt(80), r.nextInt(80), r.nextInt(80)));
            g.drawString(String.valueOf(c), (i + 1) * width / (verifyCode.length() + 1), height - 4);
        }

        return image;
    }
}

第四步:编写发送短信验证码类

新建一个SmsUtils类,用于发送短信验证码。
代码示例:

public class SmsUtils {
    private static final String ACCESS_KEY_ID = "xxxx";         // 你自己的ACCESS_KEY_ID
    private static final String ACCESS_KEY_SECRET = "xxxx";     // 你自己的ACCESS_KEY_SECRET
    private static final String SIGN_NAME = "Aliyun短信测试专用"; // 在阿里云申请的短信签名
    private static final String TEMPLATE_CODE = "SMS_0000001";  // 在阿里云申请的短信模板编号

    /**
     * 发送短信验证码
     *
     * @param phone    手机号码
     * @param verifyCode 验证码
     * @return 发送结果
     * @throws ClientException
     */
    public static SendSmsResponse sendSms(String phone, String verifyCode) throws ClientException {
        IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", ACCESS_KEY_ID, ACCESS_KEY_SECRET);
        DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", "Dysmsapi", "dysmsapi.aliyuncs.com");
        IAcsClient client = new DefaultAcsClient(profile);
        SendSmsRequest request = new SendSmsRequest();
        request.setPhoneNumbers(phone);     // 设置手机号码
        request.setSignName(SIGN_NAME);     // 设置短信签名
        request.setTemplateCode(TEMPLATE_CODE); // 设置短信模板编号
        request.setTemplateParam("{\"code\":\"" + verifyCode + "\"}"); // 设置模板参数:验证码
        SendSmsResponse response = client.getAcsResponse(request);
        return response;
    }
}

第五步:添加验证码处理器

新建一个VerifyCodeController类,用于处理验证码相关操作。
代码示例:

@Controller
public class VerifyCodeController {

    @GetMapping("/verifyCode")
    public void verifyCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
        VerifyCodeUtils.generateImage(100, 40, request, response, 4);
    }

    @GetMapping("/sendVerifyCode")
    @ResponseBody
    public String sendVerifyCode(String phone, HttpServletRequest request) throws ClientException {
        if (StringUtils.isEmpty(phone)) {
            return "请输入手机号码";
        }
        // 生成6位数字验证码
        String verifyCode = String.valueOf((int) ((Math.random() * 9 + 1) * 1_000_000));
        // 发送验证码
        SmsUtils.sendSms(phone, verifyCode);
        // 将验证码存储在Session中
        HttpSession session = request.getSession();
        session.setAttribute("verifyCode", verifyCode);
        return "success";
    }
}

第六步:添加登陆相关代码

LoginController类中添加登陆相关代码。
代码示例:

@Controller
public class LoginController {

    // 登录页面
    @GetMapping("/")
    public String login() {
        return "login";
    }

    // 登录处理
    @PostMapping("/doLogin")
    public String doLogin(String username, String password, String verifyCode, HttpSession session) {
        // 校验验证码
        String code = (String) session.getAttribute("verifyCode");
        if (StringUtils.isEmpty(code) || !code.equalsIgnoreCase(verifyCode)) {
            // 验证码错误
            return "redirect:/?error";
        }
        // 处理登录逻辑
        if ("admin".equals(username) && "123456".equals(password)) {
            return "redirect:/index";
        } else {
            return "redirect:/?error";
        }
    }

    // 首页
    @GetMapping("/index")
    public String index() {
        return "index";
    }

    // 欢迎页面
    @GetMapping("/welcome")
    public String welcome() {
        return "welcome";
    }
}

第七步:添加前端页面

最后,我们需要添加前端页面。以下是login.html页面的代码:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Login</title>
    <style>
        .form-box {
            margin: 50px auto;
            width: 320px;
            background: #fff;
            border-top: 1px solid #eee;
            border-bottom: 1px solid #eee;
            padding: 20px;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
            text-align: center;
        }

        .form-box h1 {
            font-size: 20px;
            margin-bottom: 20px;
        }

        .form-box input {
            width: 100%;
            height: 40px;
            padding: 0 20px;
            margin-bottom: 20px;
            box-sizing: border-box;
            border: 1px solid #ccc;
            border-radius: 5px;
            outline: none;
        }

        .form-box .verify-code {
            display: inline-block;
            margin-bottom: 20px;
        }

        .form-box .verify-code img {
            cursor: pointer;
            margin-left: 10px;
            vertical-align: middle;
        }

        .form-box button {
            width: 100%;
            height: 40px;
            border: none;
            border-radius: 5px;
            color: #fff;
            background: #4CAF50;
            cursor: pointer;
            outline: none;
        }

        .error {
            color: red;
        }
    </style>
    <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
</head>
<body>
<div class="form-box">
    <h1>Login</h1>
    <form action="/doLogin" method="post">
        <input type="text" name="username" placeholder="Username">
        <input type="password" name="password" placeholder="Password">
        <div class="verify-code">
            <input type="text" name="verifyCode" placeholder="Verify Code">
            <img src="/verifyCode" onclick="this.src='/verifyCode?'+Math.random()">
        </div>
        <button type="submit">Login</button>
    </form>
    <div th:if="${param.error}">
        <p class="error">Invalid username or password</p>
    </div>
</div>

<script type="text/javascript">
    $(function () {
        $('.verify-code img').click(function () {
            this.src = '/verifyCode?' + Math.random();
        });

        $('button[type="submit"]').click(function (e) {
            var phone = $('input[name="phone"]').val();
            if (phone && !/^1\d{10}$/.test(phone)) {
                alert('请输入正确的手机号码');
                e.preventDefault();
            }
            var verifyCode = $('input[name="verifyCode"]').val();
            if (verifyCode && verifyCode.length !== 4) {
                alert('验证码长度必须为4位');
                e.preventDefault();
            }
        });

        $('button[name="sendVerifyCode"]').click(function () {
            var phone = $('input[name="phone"]').val();
            if (!phone) {
                alert('请输入手机号码');
                return;
            }
            if (!/^1\d{10}$/.test(phone)) {
                alert('请输入正确的手机号码');
                return;
            }
            $.get('/sendVerifyCode?phone=' + phone, function (data) {
                if (data === 'success') {
                    var count = 60;
                    var timer = setInterval(function () {
                        count--;
                        if (count <= 0) {
                            clearInterval(timer);
                            $('button[name="sendVerifyCode"]').prop('disabled', false).text('发送验证码');
                            return;
                        }
                        $('button[name="sendVerifyCode"]').prop('disabled', true).text(count + '秒后重发');
                    }, 1000);
                } else {
                    alert(data);
                }
            });
        });
    });
</script>
</body>
</html>

至此,整个项目的实现就完成了。我们可以启动该项目并访问http://localhost:8080来体验验证码功能。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:springboot登陆页面图片验证码简单的web项目实现 - Python技术站

(0)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • Linux服务器部署JavaWeb项目完整教程

    下面我将详细讲解“Linux服务器部署JavaWeb项目完整教程”。 准备工作 在开始之前,我们需要准备以下工作: Linux服务器(我们以CentOS 7为例) JDK环境(必须安装Java Development Kit) Tomcat服务器(用于运行Java Web项目) 第一步:安装JDK 在安装JDK之前,我们需要先确认服务器上是否已经安装过JDK…

    Java 2023年5月19日
    00
  • Servlet连接数据库实现用户登录的实现示例

    下面我详细讲解一下“Servlet连接数据库实现用户登录的实现示例”的完整攻略。 什么是Servlet连接数据库 Servlet连接数据库,指的是在Java Servlet中,通过使用各种数据库的API接口,连接对应的数据库来实现数据的增、删、改、查操作。对于实现用户登录功能来说,数据库中需要储存用户的账号和密码,以供用户在登录时进行认证。 实现步骤 第一步…

    Java 2023年6月16日
    00
  • Android实现APP自动更新功能

    让我来讲解一下,“Android实现APP自动更新功能”的完整攻略。 1. 什么是APP自动更新功能? APP自动更新功能是指当我们开发的APP有新版本发布时,用户打开APP后会自动检测更新并提示用户更新。此功能可以为用户提供最新的APP版本,同时也可以让应用开发者方便地推出新版本并使用户及时更新升级。 2. 如何实现APP自动更新功能? 要实现APP自动更…

    Java 2023年5月23日
    00
  • 使用Spring Boot实现操作数据库的接口的过程

    使用Spring Boot实现操作数据库的接口的过程大致可以分为以下几个步骤: 准备工作:创建一个Spring Boot项目并添加必要的依赖。 配置数据库连接:在application.properties文件中配置数据库的连接信息,如数据库的URL、用户名、密码等。 定义数据模型:创建一个Java类来表示数据库中的数据表,包括表的字段和相关方法。 定义数据…

    Java 2023年5月20日
    00
  • SpringBoot配置项目访问路径URL的根路径方式

    在Spring Boot应用程序中,我们可以使用配置文件或注解的方式来配置项目访问路径URL的根路径。本文将详细介绍如何使用这两种方式来配置项目访问路径URL的根路径,并提供两个示例说明。 1. 使用配置文件配置项目访问路径URL的根路径 在Spring Boot应用程序中,我们可以使用application.properties或application.y…

    Java 2023年5月18日
    00
  • 使用maven编译Java项目实例

    使用Maven编译Java项目的完整攻略,主要分为以下几个步骤: Step 1:准备工作 在开始编译Java项目之前,需要确保已经安装好了以下软件和环境: JDK:确保已经安装了JDK,并设置了JAVA_HOME环境变量。 Maven:需要先安装Maven,并将其添加到PATH环境变量中。 Step 2:创建项目 在本地计算机上创建一个Java项目,并使用M…

    Java 2023年5月20日
    00
  • java实现航班信息查询管理系统

    Java实现航班信息查询管理系统攻略 系统概述 航班信息查询管理系统是管理机场航班信息的系统,它可以提供航班信息的查询、添加、修改和删除等功能。该系统使用Java语言进行开发,采用MVC架构,使用MySQL数据库存储数据。 系统需求 该系统具备以下功能: 前端页面展示所有航班信息。 管理员登录,可添加、修改和删除航班信息。 普通用户不需要登录,可查询航班信息…

    Java 2023年5月24日
    00
  • Java SpringMVC框架开发之数据导出Excel文件格式实例详解

    Java SpringMVC框架开发之数据导出Excel文件格式实例详解 前言 在Web应用程序中,数据导出的需求是比较常见的。本文介绍如何在Java SpringMVC框架中开发,实现将数据导出到Excel文件格式的功能。本文的示例代码基于SpringMVC 5.2.5版本和Apache POI 4.1.2版本实现。 准备工作 在开始本文的实例之前,需要做…

    Java 2023年6月3日
    00
合作推广
合作推广
分享本页
返回顶部