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

Posted Silent1376

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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"
                });
            }
        });
    });

 

以上是关于Project原生JavaWeb工程 02 登陆业务的流程(第一阶段样例)的主要内容,如果未能解决你的问题,请参考以下文章

Project原生JavaWeb工程 03 单表的业务功能

java web工程引用java project(以二维码和加密为例)

Intellijidea建javaWeb以及Servlet简单实现

Intellij IDEA创建javaweb步骤详解

Intellij idea创建javaWeb以及Servlet简单实现

JAVAWEB 一一 userweb1(原生,非servlet版,用doXXX.jsp代替servlet)