Java生成动态验证码与仿登录时验证码的校验

需求分析与实现思路:

会话技术使用场景——验证码校验

进入登录页面时请求CheckCodeServlet生成验证码,并把验证码的值保存到session里,当用户提交登录表单时,使用validator插件进行表单校验,除验证码外的其他参数都校验通过后,使用validator插件提供的方式不提交表单,而是把表单提交的验证码值作为参数使用AJAX发送异步请求,在服务端(LoginServlet)从session里获取保存的验证码的值和表单提交的验证码值进行比较,把结果返回给客户端做相应处理。
在这里插入图片描述

代码示例:

在这里插入图片描述

  • 登录页面。 (login.html)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
    <style type="text/css">
        table {
            width: 30%;
            margin:auto;
            position: absolute;
            right: 0;
            left: 0;
        }
        /*验证码效验不通过时提示的字体颜色*/
        .showtip {
           color: red;
        }
        /*validator插件效验不通过时提示的字体颜色*/
        .error{
            color:red;
        }
    </style>

</head>
<body>


<form name="empForm" id="empForm" method="post" action="#">
    <table>
        <tr>
            <td>用户名</td>
            <td><input type="text" id="username" name="username" autocomplete="off" /></td>
        </tr>

        <tr>
            <td>密码</td>
            <td><input type="password" id="pwd" name="pwd" /></td>
        </tr>

        <tr>
            <td>验证码</td>
            <td>
                <input type="text" name="check" id="check" autocomplete="off">
                <!--该项目的context路径为 /test , src属性值是图像文件的URL ,这里请求/test/checkCode,CheckCodeServlet会响应输出验证码图片-->
                <img src="/test/checkCode"  id="checkImg" alt="" onclick="changeImage(this)">
                <label class="showtip" id="vfcodelab" ></label>
            </td>
        </tr>

        <tr>
            <td></td>
            <td><input type="submit" id="smtBtn" value="登录"></td>
        </tr>
    </table>
</form>

<!--导入jquery-->
<script src="js/jquery-1.11.0.min.js"></script>
<!-- 引入validator插件 -->
<script src="js/jquery.validate.min.js"></script>

<script>

    //点击时切换验证码,改验证码图片的src属性值。
    function changeImage(obj) {
        //每次点击时,要保证src属性值是变化的,否则浏览器会从缓存里取图片显示,而不会发请求重新请求图片。
        //如何让src属性值是变化:在发请求时,可以在请求路径的后边,通过?追加一些参数(参数随机),这样每次src属性值都是变化的。
        //请求路径?参数名=参数值就等价于表单的get提交的参数,请求到达CheckCodeServlet,动态生成验证码,再输出到页面,对于参数是何值有没有参数这些都不重要。
        obj.src = "/test/checkCode?a=" + Math.random();
    }

	//表单校验
    $("#empForm").validate({
        submitHandler:function(){//校验通过后,表单不提交,而是执行function里的代码
            var params = $("#empForm").serialize();
            $.post("login",params,function (result) {
                if(result.ok){//验证码验证通过
                    alert("验证码验证通过")
                }else{//验证码验证不通过
                    $("#vfcodelab").show()
                   $("#vfcodelab").text(result.msg);
                   //点击切换验证码
                   $("#checkImg").click();
                }
            },"json")
        },
        rules:{//配置表单项校验的规则
            username:{
                required: true
            },
            pwd:{
                required: true,
                rangelength:[6,12]
            }

        },
        messages:{//配置对应的表单项校验失败后的错误提示信息
            username:{
                required: "请输入用户名"
            },
            pwd:{
                required: "请输入密码",
                rangelength:"密码必须是6~12位"
            }
        }
    })

    //验证码验证不通过时,点击验证码输入框,重新输入时把提示隐藏
    $("#check").click(function () {
        $("#vfcodelab").hide();
    })

</script>
</body>
</html>
  • 验证码图片请求,Java生成验证码,响应客户端,登录页面再显示验证码。 (CheckCodeServlet)

注:网络资源,供参考

/**
 * Java生成验证码,响应客户端
 */
@WebServlet("/checkCode")
public class CheckCodeServlet extends HttpServlet {
	@Override
	public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
		
		//服务器通知浏览器不要缓存
		response.setHeader("pragma","no-cache");
		response.setHeader("cache-control","no-cache");
		response.setHeader("expires","0");
		
		//在内存中创建一个长80,宽30的图片,默认黑色背景
		//参数一:长
		//参数二:宽
		//参数三:颜色
		int width = 80;
		int height = 30;
		BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
		
		//获取画笔
		Graphics g = image.getGraphics();
		//设置画笔颜色为灰色
		g.setColor(Color.GRAY);
		//填充图片
		g.fillRect(0,0, width,height);
		
		//产生4个随机验证码,12Ey
		String checkCode = getCheckCode();
		//将验证码放入HttpSession中
		request.getSession().setAttribute("CHECKCODE_SERVER",checkCode);
		
		//设置画笔颜色为黄色
		g.setColor(Color.YELLOW);
		//设置字体的小大
		g.setFont(new Font("黑体",Font.BOLD,24));
		//向图片上写入验证码
		g.drawString(checkCode,15,25);
		
		//将内存中的图片输出到浏览器
		//参数一:图片对象
		//参数二:图片的格式,如PNG,JPG,GIF
		//参数三:图片输出到哪里去
		ImageIO.write(image,"PNG",response.getOutputStream());
	}
	/**
	 * 产生4位随机字符串 
	 */
	private String getCheckCode() {
		String base = "0123456789ABCDEFGabcdefg";
		int size = base.length();
		Random r = new Random();
		StringBuffer sb = new StringBuffer();
		for(int i=1;i<=4;i++){
			//产生0到size-1的随机值
			int index = r.nextInt(size);
			//在base字符串中获取下标为index的字符
			char c = base.charAt(index);
			//将c放入到StringBuffer中去
			sb.append(c);
		}
		return sb.toString();
	}
	@Override
	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		this.doGet(request,response);
	}
}

  • 登录页面表单校验,AJAX异步发送请求,效验表单提交验证码与服务端保存的验证码是否相同,并响应客户端 。(LoginServlet)
@WebServlet(name = "LoginServlet",urlPatterns ="/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        ResultInfo info=null;
        response.setContentType("text/html;charset=utf-8");
        request.setCharacterEncoding("UTF-8");
		//接收参数
        //String username = request.getParameter("username");
        //String password = request.getParameter("password");
        String check = request.getParameter("check");
		//完成功能
        	//先验证验证码是否正确
        String checkcode_server = (String) request.getSession().getAttribute("CHECKCODE_SERVER");
        if(check.equalsIgnoreCase(checkcode_server)){
        	//封装后端返回前端的数据
            info=new ResultInfo(true);
        }else{
            info=new ResultInfo(false,"验证码填写错误");
        }
       	//处理结果
        ObjectMapper mapper = new ObjectMapper();
        String json = mapper.writeValueAsString(info);
        response.getWriter().print(json);
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    }
}

  • 封装后端返回前端的数据,Java对象转换为json字符串,登录页面AJAX异步请求接收到json对象 (ResultInfo)

注:网络资源,供参考

/**
 * 用于封装后端返回前端数据对象。对应json格式:{"ok":true, "data":{结果数据}, "msg":"消息描述"}
 */
public class ResultInfo implements Serializable {
    private boolean ok;//后端返回结果正常为true,发生异常返回false
    private Object data;//后端返回结果数据对象
    private String msg;//描述消息。如果发生异常,则是错误信息

    public ResultInfo() {
    }

    /**
     * @param ok 是否正常处理完成
     */
    public ResultInfo(boolean ok) {
        this.ok = ok;
    }

    /**
     * @param ok 是否正常处理
     * @param data 处理结果数据
     */
    public ResultInfo(boolean ok, Object data) {
        this.ok = ok;
        this.data = data;
    }

    /**
     * @param ok 是否正常处理
     * @param msg  消息描述
     */
    public ResultInfo(boolean ok, String msg) {
        this.ok = ok;
        this.msg = msg;
    }

    /**
     * @param ok 是否正常处理
     * @param data 返回数据
     * @param msg  消息描述
     */
    public ResultInfo(boolean ok, Object data, String msg) {
        this.ok = ok;
        this.data = data;
        this.msg = msg;
    }

    public boolean isOk() {
        return ok;
    }

    public void setOk(boolean ok) {
        this.ok = ok;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
}
发布了48 篇原创文章 · 获赞 18 · 访问量 2934

猜你喜欢

转载自blog.csdn.net/qq_45615417/article/details/104428562