SpringMVC——注册登陆功能模块的实现(2)

  • 此篇博文是上一篇的续篇,内容包括
    1)登陆按钮功能逻辑代码的前端和后端编辑
    2)注册按钮功能逻辑代码的前端和后端编辑
    3)密码字段加密解密
    4)避免多端设备登陆的处理
    5)避免账号重复注册的处理

一、注册功能逻辑代码编写

1、前端部分

  • 进行注册时,学号和密码的输入一定不能为空,同时密码字段长度也不能少于8个字符,只要上述两种情况发生一个,都应该拒绝注册,并弹出提示框,提示用户重新输入。
  • 这部分功能可以在前端页面用Javascript来实现,其代码如下:
    <script>
       function check(stuId,password) {
            if(stuId.value!==""&&password.value!=="")
            {
                if(password.value.length>=8)
                    return true;
            }
            alert("学号和密码为空,或密码长度小于8");
            return false;
        }
    </script>
    
  • 这时候要在 form 表单的onsubmit 添加代码:onsubmit="return check(form.stuID,form.password)"。加了词句代码后,只有当学号和密码字段长度大于8,浏览器才会将表单提交给服务器,否则表单不会提交给服务器,注册便不会成功。

2、后端部分

  • 后端要实现的功能代码是,首先对表单提交上来的学号,拿到 User 表中进行匹配,若出现相同学号则,则终止注册行为,返回前端相关提示信息;若尚未注册,则进行密码字段加密,然后再将加密后的密码和学号存储到 User 表中,而把其他信息存储到 UserInfo 表中。

2.1、加密解密方法类

  • 在项目目录里新建一个 function package 用于存放一些使用工具方法,例如这个加密解密方法。该方法的代码如下:
    //IntelliJ IDEA
    //springmvcstudent
    //OptPassword
    //2021/1/7
    // Author:御承扬
    //E-mail:2923616405@qq.com
    
    package com.pyc.springmvcstudent.function;
    
    import javax.crypto.Cipher;
    import java.security.Key;
    
    public class OptPassword {
        // 字符串默认键值
        private static String strDefaultKey = "inventec2020@#$%^&";
    
        //加密工具
        private Cipher encryptCipher = null;
    
        // 解密工具
        private Cipher decryptCipher = null;
    
        /**
         * 默认构造方法,使用默认密钥
         */
        public OptPassword() throws Exception {
            this(strDefaultKey);
        }
    
        /**
         * 指定密钥构造方法
         * @param strKey 指定的密钥
         * @throws Exception
         */
    
        public OptPassword(String strKey) throws Exception {
    
            // Security.addProvider(new com.sun.crypto.provider.SunJCE());
            Key key = getKey(strKey.getBytes());
            encryptCipher = Cipher.getInstance("DES");
            encryptCipher.init(Cipher.ENCRYPT_MODE, key);
            decryptCipher = Cipher.getInstance("DES");
            decryptCipher.init(Cipher.DECRYPT_MODE, key);
        }
    
        /**
         * 将byte数组转换为表示16进制值的字符串, 如:byte[]{8,18}转换为:0813,和public static byte[]
         *
         * hexStr2ByteArr(String strIn) 互为可逆的转换过程
         *
         * @param arrB 需要转换的byte数组
         * @return 转换后的字符串
         * @throws Exception  本方法不处理任何异常,所有异常全部抛出
         */
        public static String byteArr2HexStr(byte[] arrB) throws Exception {
            int iLen = arrB.length;
            // 每个byte用2个字符才能表示,所以字符串的长度是数组长度的2倍
            StringBuffer sb = new StringBuffer(iLen * 2);
            for (int i = 0; i < iLen; i++) {
                int intTmp = arrB[i];
                // 把负数转换为正数
                while (intTmp < 0) {
                    intTmp = intTmp + 256;
                }
                // 小于0F的数需要在前面补0
                if (intTmp < 16) {
                    sb.append("0");
                }
                sb.append(Integer.toString(intTmp, 16));
            }
            return sb.toString();
        }
    
        /**
         * 将表示16进制值的字符串转换为byte数组,和public static String byteArr2HexStr(byte[] arrB)
         * 互为可逆的转换过程
         * @param strIn 需要转换的字符串
         * @return 转换后的byte数组
         */
        public static byte[] hexStr2ByteArr(String strIn) throws Exception {
            byte[] arrB = strIn.getBytes();
            int iLen = arrB.length;
            // 两个字符表示一个字节,所以字节数组长度是字符串长度除以2
            byte[] arrOut = new byte[iLen / 2];
            for (int i = 0; i < iLen; i = i + 2) {
                String strTmp = new String(arrB, i, 2);
                arrOut[i / 2] = (byte) Integer.parseInt(strTmp, 16);
            }
            return arrOut;
        }
    
        /**
         *
         * 加密字节数组
         * @param arrB 需加密的字节数组
         * @return 加密后的字节数组
         */
        public byte[] encrypt(byte[] arrB) throws Exception {
            return encryptCipher.doFinal(arrB);
        }
    
        /**
         * 加密字符串
         * @param strIn 需加密的字符串
         * @return 加密后的字符串
         */
        public String encrypt(String strIn) throws Exception {
            return byteArr2HexStr(encrypt(strIn.getBytes()));
        }
    
        /**
         * 解密字节数组
         * @param arrB 需解密的字节数组
         * @return 解密后的字节数组
         */
        public byte[] decrypt(byte[] arrB) throws Exception {
            return decryptCipher.doFinal(arrB);
        }
    
        /**
         * 解密字符串
         * @param strIn 需解密的字符串
         * @return 解密后的字符串
         */
        public String decrypt(String strIn) throws Exception {
            return new String(decrypt(hexStr2ByteArr(strIn)));
        }
    
        /**
         * 从指定字符串生成密钥,密钥所需的字节数组长度为8位 不足8位时后面补0,超出8位只取前8位
         * @param arrBTmp 构成该字符串的字节数组
         * @return 生成的密钥
         */
        private Key getKey(byte[] arrBTmp) throws Exception {
            // 创建一个空的8位字节数组(默认值为0)
            byte[] arrB = new byte[8];
            // 将原始字节数组转换为8位
            for (int i = 0; i < arrBTmp.length && i < arrB.length; i++) {
                arrB[i] = arrBTmp[i];
            }
            // 生成密钥
            Key key = new javax.crypto.spec.SecretKeySpec(arrB, "DES");
            return key;
        }
    }
    
  • 接着就是具体的注册功能逻辑代码实现,在WebController 里面新建一个接口方法,如下面代码:
    @RequestMapping("/sign")
    public String Sign(Model model, @Param("stuID")String stuID,
                       @Param("password")String password,
                       @Param("stuName")String stuName,
                       @Param("profession")String profession,
                       @Param("stuClass")String stuClass,
                       @Param("broth")String broth,
                       @Param("tel")String tel){
        User u = userRepository.findAllByStudentID(stuID);
        Msg msg = new Msg("","");
        if(u!=null){
            msg.setTitle("错误");
            msg.setContent("该学号已被注册,请将能证明你是该学号拥有者的资料,发送到管理员邮箱:");
            model.addAttribute("msg",msg);
            return "page/Sign";
        }
        try {
            OptPassword op = new OptPassword();
            String encodePassword = op.encrypt(password);
            User user = new User(stuID, encodePassword);
            userRepository.save(user);
        }catch (Exception e){
            System.out.println(e.getMessage());
        }
        UserInfo userInfo = new UserInfo(stuID,stuName,profession,stuClass,broth,tel);
        userInfoRepository.save(userInfo);
        msg.setTitle("系统提醒");
        msg.setContent("注册成功,请前往登陆页面登陆");
        model.addAttribute("msg",msg);
        return "page/Sign";
    }
    
  • @RequestMapping 注解将该方法转换成一个接口方法,前端可以通过调用接口来访问该方法,访问方式一般有:
    1)form 的 action,action="/sign";
    2)button 的 onclick,οnclick=“windows.location.href=’/sign’”;
    3) a 的 href,href=“/sign";
  • 这里使用第一中方式,此时 sign 页面的 form 头变成:<form class="form-horizontal" name="form" style="width: 500px" method="post" action="/sign" th:action="@{/sign}"onsubmit="return check(form.stuID,form.password)">

二、登陆功能逻辑代码编写

1、前端部分

  • 同样的,登陆时,输入框不得为空,并且密码和确认密码应当一致,否则拒绝登陆,弹出提示。这部分功能,仍旧采用 Javascript 实现,实现代码如下:
    <script>
        function check(stuID, password,checkPassword) {
            let si = stuID.value;
            let p = password.value;
            let cp = checkPassword.value;
            if(si!==""&&p!==""&&cp!=="")
            {
                if(p===cp)
                    return true;
            }
            alert("密码不一致,或输入为空");
            return false;
        }
    </script>
    
  • 调用方式和注册页面的一样,都是在 form 标头里的 onsubmit 中。

2、后端部分

  • 后端要将表单提交的信息中,首先根据输入的学号到 UserInfo 表中查询登陆字段的值,若为 true,则拒绝当前设备的登陆,返回提示,提示该账户已在其他设备登陆。若未登录,则根据输入的学号到 User 表中获取对应记录的密码字段,并将密码字段进行解密操作,若解密后的与输入的密码一致,则登陆成功,见 UserInfo 中的登陆更新为 True 并跳转到 home 页面。
  • 上述功能逻辑代码如下:
    @RequestMapping("/login")
        public String Login(Model model,@Param("stuID")String stuID,
                            @Param("password")String password){
            User u = userRepository.findAllByStudentID(stuID);
            UserInfo ui = userInfoRepository.findAllByStuID(stuID);
            boolean key=false;
            if(!ui.getOnline()){
                try{
                    OptPassword op = new OptPassword();
                    String decodePassword = op.decrypt(u.getPassword());
                    if(decodePassword.equals(password))
                    {
                       int t= userInfoRepository.setOnlineByStuID(true,stuID);
                       if(t!=0)
                           key=true;
                    }
                }catch (Exception e){
                    System.out.println(e.getMessage());
                }
                if(key){
                    Msg msg = new Msg("系统信息",ui.getName()+",欢迎使用学生信息管理系统!");
                    model.addAttribute("msg",msg);
                    return "page/Home";
                }
                Msg msg = new Msg("系统信息","登陆失败!");
                model.addAttribute("msg",msg);
                return "Error";
            }
            Msg msg = new Msg("系统信息","登陆失败,因为当前账号已在其他设备进行登陆");
            model.addAttribute("msg",msg);
            return "Error";
        }
    
  • 将登陆表单的 form 标头更改为:<form class="form-horizontal" name="form" style="width: 500px" method="post" action="/login" th:action="@{/login}"onsubmit="return check(form.stuID,form.password,form.CheckPassword)">
  • Error 页面:
    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org" lang="en">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
        <title>错误页面</title>
    </head>
    <body>
    <div class="container">
        <div class="row">
            <br>
            <br>
            <br>
            <div class="col-md-8">
                <div class="panel panel-primary">
                    <div class="panel-heading">
                        <h2 class="panel-title">
                            提示信息:
                        </h2>
                    </div>
                    <div class="panel-body" th:if="${ not #lists.isEmpty(msg)}">
                        <div class="panel-info">
                            <h4 th:text="${msg.getTitle()}"></h4><h5 th:text="${msg.getContent()}"></h5>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    </body>
    
  • 由于先暂时进行登陆功能逻辑测试,Home 页面布局暂不用编辑,如下:
    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org" lang="en">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
        <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"
              integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
              crossorigin="anonymous">
    
        <!-- 可选的 Bootstrap 主题文件(一般不用引入) -->
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap-theme.min.css"
              integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp"
              crossorigin="anonymous">
    
        <!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"
                integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"
                crossorigin="anonymous"></script>
        <title>Home</title>
    </head>
    <body>
    <div class="container">
        <div class="row">
            <br>
            <br>
            <br>
            <div class="col-md-8">
                <div class="panel panel-primary">
                    <div class="panel-heading">
                        <h2 class="panel-title">
                            提示信息:
                        </h2>
                    </div>
                    <div class="panel-body" th:if="${ not #lists.isEmpty(msg)}">
                        <div class="panel-info">
                            <h4 th:text="${msg.getTitle()}"></h4><h5 th:text="${msg.getContent()}"></h5>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    </body>
    
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Spring MVC 是一个基于 Java 的 Web 框架,用于快速开发 Web 应用。如果您想使用 Spring MVC 实现登录注册功能,可以按照以下步骤操作: 1. 创建一个新的 Spring MVC 项目并配置相关的依赖。 2. 定义用户模型,并在数据库中创建一个表存储用户信息。 3. 创建一个控制器处理登录注册请求。控制器会调用与数据库交互的服务层代码完成相关操作。 4. 创建服务层代码,实现数据库操作。 5. 创建视图,提供登录注册界面。 6. 配置 Spring MVC 的路由,使控制器和视图可以正确的对应。 7. 启动项目并测试登录注册功能。 以上是实现登录注册功能的大致步骤,具体的实现细节可能因项目的不同而有所差异。希望以上信息能对您有所帮助。 ### 回答2: 使用Spring MVC实现登录注册功能有以下步骤: 1. 创建Maven项目并添加所需的依赖,包括Spring Web和相关数据库驱动。 2. 创建数据库表,包括用户表和相关字段,如用户名、密码等。 3. 创建实体类User,包含用户的属性,并使用注解将其与数据库表关联。 4. 创建数据访问层接口和实现类,用于对数据库进行CRUD操作,在实现类中,使用注解将查询结果映射到实体类中。 5. 创建业务逻辑层接口和实现类,负责处理用户登录注册的业务逻辑,调用数据访问层的方法进行数据库操作。 6. 创建控制器类,使用注解标记为控制器,并注入业务逻辑层的接口,处理用户的请求和返回结果,如登录请求和注册请求。 7. 在控制器类中,实现登录注册的处理方法,使用注解标记为处理请求的方法,并根据业务逻辑层返回的结果,返回对应的视图或JSON数据。 8. 创建页面模板,包括登录页面和注册页面,使用HTML、CSS和JavaScript编写,设置相应的表单和输入字段。 9. 配置Spring MVC的配置文件,包括视图解析器、处理器映射器、静态资源处理器等,以及Spring的配置文件,包括数据源配置和事务管理。 10. 启动项目并部署到服务器,访问登录注册页面,通过输入用户名和密码进行登录注册操作。 以上就是使用Spring MVC实现登录注册功能的步骤。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

御承扬

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值