• 【Project】原生JavaWeb工程 02 登陆业务的流程(第一阶段样例)


    1、对用户信息的描述

    首先用户有一些基本信息:

    最简单的:

    用户名称 + 用户密码

    然后是用户状态,例如封号,注销,停用,等等

    用户名称 + 用户密码 + 账号状态

    接着为了防止脚本攻击,又产生了图形码验证,为了区分人和机器

    用户名称 + 用户密码 + 用户状态 + 图形验证码

    2、过程设计:

    所以按照最后的这种形式,我们设计一个登陆业务的过程

    首先用户在界面上看到三个东西:

    - 名称框

    - 密码框

    - 验证码框

    由于账号状态由后台控制,所以这里不会出现,也不会给用户查看

    用户名是否会产生重复?

    这个问题可以在注册的时候进行业务控制,

    也就是说,我们是在一个用户名不会重复的前提下设计的

    第一点:

      三个框框都是必须填入信息的,这是第一限制

    第二点:

      基于上面用户名不重复的前提上,如果用户输入不存在的用户名就应该限制,并作出提示,用户不存在

    第三点:

      根据用户提供的名称获取到对应的密码,就开始对密码进行匹配,如果错误,则限制,并作出提示,密码错误

    第四点:

      检查验证码是否匹配,如果错误则限制,并作出提示

    而限制是在页面上实现,服务器则负责信息校验的问题:

    所以我们的页面和服务器职责是明确的。

    对用户的输入信息进行控制,符合第一道工序之后传输信息给服务器,

    服务器根据提供的信息进行校验,然后反馈给页面,

    页面对反馈信息进行对应的处理,实现页面的限制

    所以数据库的用户表设计根据这个业务的需要

    至少提供:

    用户名|用户密码|账号状态|

    验证码是随机生成的,不应该存储在数据库,且浪费存储资源

    前置的总结:

    但是我没有想到的是可以使用JS来处理页面之间的跳转

    因为之前的案例都是通过表单完成,这个步骤完全没有JS来参与逻辑控制

    然后后端的事情显得非常的明确,我要做的业务其实也只是查询需要的结果打包给前端

    信息校验在业务中处理,然后返回

    具体实现描述

    JS在发送Ajax之前进行控制,给服务后由程序对数据库访问,查询的结果和用户输入比较

    再来是验证码校验,然后返回信息给前端,只有对的JS页面跳转,其他弹窗警告

    3、具体实现的代码:

    验证码图片生成和保存验证码:

    应该简称ImageIDServlet

    package cn.dzz.servlet;
    
    import javax.imageio.ImageIO;
    import javax.servlet.ServletOutputStream;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.awt.*;
    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.util.Random;
    
    /**
     * @author ArkD42
     * @file OA
     * @create 2020 - 06 - 18 - 10:01
     */
    
    @WebServlet("/verify")
    public class VerificationCodeServlet extends BaseServlet{
    
        /**
         * /verify?act=genImage
         * @param request
         * @param response
         * @throws IOException
         */
        public void genImage(HttpServletRequest request, HttpServletResponse response) throws IOException {
            // 设置图片的宽高
            int width = 60, height = 20;
    
            // 创建具有可访问图像数据缓冲区的Image
            BufferedImage bufferedImage = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);
            Graphics2D graphics2D = bufferedImage.createGraphics();
    
            // 创建一个随机数生成对象
            Random random = new Random();
    
            graphics2D.setColor(Color.WHITE);
            graphics2D.fillRect(0, 0, width, height);
    
            // 创建字体,字体的大小应该根据图片的高度来定
            Font font = new Font("微软雅黑", Font.PLAIN, 18);
    
            // 设置字体
            graphics2D.setFont(font);
    
            // 画边框
            graphics2D.setColor(Color.BLACK);
            graphics2D.drawRect(0, 0, width - 1, height - 1);
    
            // 随机产生160条干扰线
            graphics2D.setColor(Color.LIGHT_GRAY);
            for (int i = 0; i < 160; i++) {
                int x = random.nextInt(width);
                int y = random.nextInt(height);
                int x1 = random.nextInt(12);
                int y1 = random.nextInt(12);
                graphics2D.drawLine(x, y, x + x1, y + y1);
            }
    
            // randomCode 用于保存随机产生的验证码
            StringBuffer randomCode = new StringBuffer();
            int red = 0, green = 0, blue = 0;
    
            // 随机产生4位数字的验证码
            for (int i = 0; i < 4; i++) {
                // 得到随机产生的验证码数字
                String strRand = String.valueOf(random.nextInt(10));
    
                // 产生随机的颜色分量来构造颜色值
                red = random.nextInt(110);
                green = random.nextInt(50);
                blue = random.nextInt(50);
    
                // 用随机产生的颜色将验证码绘制到图像中
                graphics2D.setColor(new Color(red, green, blue));
                graphics2D.drawString(strRand, 13 * i + 6, 16);
    
                randomCode.append(strRand);
            }
    
            // 将四位数字的验证码保存到session中
            request.getSession().setAttribute("randomCode", randomCode.toString());
            System.out.println(this.getClass().getName() + " 生成的验证码:" + randomCode.toString());
    
            // 禁止图像缓存
            response.setHeader("Pragma", "no-cache");
            response.setHeader("Cache-Control", "no-cache");
            response.setDateHeader("Expires", 0);
    
            response.setContentType("image/jpeg");
            // 将图像输出到servlet输出流中
            ServletOutputStream sos = response.getOutputStream();
            ImageIO.write(bufferedImage, "jpeg", sos);
            sos.close();
        }
    
    }

    然后在登录页的事件绑定:

    <img
            src="verify?act=genImage"
            id="verify_img"
            title="看不清?换一张"
            name="verify_img"
            align="middle"
            onclick="loadImage();return false;"
    />
    
    <script type="text/javascript">
    
        function loadImage(){
            document.getElementById("verify_img").src="verify?act=genImage&time=" + new Date().getTime();
        }
    </script>

    在Dao层中需要的实现:

        @Override
        public User queryUserByName(String username) {
            final String SQL = "SELECT * FROM t_user WHERE user_name = ?";
            return JdbcForTxUtil.queryOne(
                    TransactionManager.getCurrentThreadConnection(),
                    User.class,
                    SQL,
                    new Object[]{username}
            );
        }

    然后是登陆业务实现:

        @Override
        public JsonResult login(HttpServletRequest request) {
    
            // 验证码的验证
            HttpSession session = request.getSession();
            String randomCode = session.getAttribute("randomCode").toString();
            String imgID = request.getParameter("imgID");
            System.out.println(request.getRemoteAddr() + "用户输入的是:" + imgID + " 从Session得到的是:" + randomCode);
    
            if (!(randomCode.equals(imgID))) return new JsonResult(500,"验证码错误",null);
    
            // 用户信息验证
            String username = request.getParameter("username");
            String password = request.getParameter("password");
    
            User user = userDao.queryUserByName(username);
            System.out.println(user);
    
            if (user == null) return new JsonResult(200,"没有此用户",null);
    
            else {
                if (!(password.equals(user.getUser_password()))) return new JsonResult(300,"密码错误",null);
                else if (user.getUser_status() != 1) return new JsonResult(400,"账号状态异常",null);
            }
    
            session.setAttribute("userInfo",user);
    
            return new JsonResult(100,"验证通过",null);
        }

    登陆Servlet反馈给登录页

        /**
         * /login?act=loginCheck
         * 处理从/WEB-INF/jsp/login.jsp页的表单发送的请求,进行信息校验
         * @param request
         * @param response
         * @return
         */
        public JsonResult loginCheck(HttpServletRequest request, HttpServletResponse response) {
            JsonResult result = loginService.login(request);
            return result;
        }

    最后是由登录页的JS处理

    /* 登陆验证 */
        $(function () {
            $("#loginBtn").click(function () {
    
                let username= $("#username").val();
                let password= $("#password").val();
                let imgID= $("#imgID").val();
    
                if(username === "" || password === "" || imgID === "") {
                    alert("请输入用户或密码或验证码!!!");
                } else {
                    //ajax 登录
                    let url = "/login?act=loginCheck";
                    let obj = {
                        username:username,
                        password:password,
                        imgID:imgID
                    }
                    $.ajax({
                        url: url,
                        type: "post",
                        data: obj,
                        success: function (data) {
    
                            /* 不要使用全等,JS会把对象和字符串比较类型,对不上就不走了 */
                            if (data.feedbackStatus == "100") location.href="/home";       // 状态100 验证通过
                            else if (data.feedbackStatus == "200") alert(data.messageses); // 状态200 用户不存在
                            else if (data.feedbackStatus == "300") alert(data.messageses); // 状态200 密码错误
                            else if (data.feedbackStatus == "400") alert(data.messageses); // 状态400 账号状态异常
                            else if (data.feedbackStatus == "500") alert(data.messageses); // 状态500 验证码错误
                        },
                        dataType:"json"
                    });
                }
            });
        });
  • 相关阅读:
    iOS的几种动画使用
    iOS工程师必备技能
    网络数据的下载(NSUrlconnection异步下载和NSstring同步下载)和UI界面数据的刷新(都是抛弃第三方库的一些本质)
    GCD定时器
    iOS开发的小技巧
    站在巨人的肩膀上
    跳转系统设置相关界面的方法
    微信分享
    网站 、内容
    加水印
  • 原文地址:https://www.cnblogs.com/mindzone/p/13174405.html
Copyright © 2020-2023  润新知