带你一步一步实现验证码登录和自动登录

1.实现最简单的登录

首先,要想实现验证码和自动登录就要弄清楚登录这个过程中有多少步骤,那么接下来我来说说我的登录逻辑。

首先,要实现登录,必须要servlet去验证输入的用户名和密码是否正确,
那么简单的servlet就出炉了:

package com.ps.Servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;

//这里配置的就是以后表单要提交的地址
@WebServlet(urlPatterns = "/Login")
public class LoginServlet extends HttpServlet {

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

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取数据
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        //在这里应该是把参数传给数据库来判断的,为了简便演示,我就先这么写了
        if ("admin".equals(username) && "123456".equals(password)) {
			//把登录后的信息存储在会话域中,方面访问别的页面使用
			session.setAttribute("username", username);
			//跳转到index页面
			response.sendRedirect("index.jsp");
		} else {
			//输入的信息错误,跳回到原页面,需要重新输入
			request.getRequestDispatcher("login.html").forward(request, response);
		}
}

2.过滤器处理中文乱码

写到这里实现并运行过的小伙伴就会发现一个问题,那就有些时候传入的参数会乱码,尤其是在传入中文的时候会乱码。

原因是我没有处理请求的编码格式,这是为什么呢?

因为在比较大的项目中,这种问题经常会出现,如果每个servlet里面都加入的话,就比较麻烦,为了不麻烦,那我们编写一个处理请求参数乱码问题的过滤器(filter)就好了。

不会没有关系,代码在下面:

package com.ps.Filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 目标:
 * 拦截请求,把涉及到登录和注册的请求拦截下来,修改请求编码避免获取参数的时候乱码
 */
 //这里配置的就是servlet1的路径配置成完全一样的就好了
@WebFilter(urlPatterns = "/Login")
public class RequestFilter implements Filter {
    public void destroy() {
    
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //1.强性把类型转换,便于操作
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        //2.修改编码,防止乱码
        request.setCharacterEncoding("utf-8");
        //3.放行
        chain.doFilter(request, response);
    }

    public void init(FilterConfig config) throws ServletException {

    }
}

3.编写最简单前端页面

写完上面两个步骤的话,我们就可以先写一个前端页面来测试一下了。


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>login</title>
</head>
<body>
<h2>用户登录</h2>
<!--form的id是为了以后自动登录的时候获取,method就是请求的方法,action就是请求的servlet地址,就是前面配置的那个-->
<form action="Login" method="post" id="loginForm">
    <!--name属性是给servlet获取值的-->
    用户名:&nbsp;<input name="username" type="text">
    <br>
    <br>
    密码:&nbsp;<input name="password" type="password">
    <br>
    <br>
    <input value="登录" type="submit">
</form>
</body>
</html>

以上,就是最简单的一个登录功能的实现了,我相信都已经跟的上了,那么接下来我们就稍稍微微的加快点速度

4.编写验证码servlet

这里其实没有太多好说的,都是比较固定的东西,所以看看就好。

package com.ps.Servlet;

import javax.imageio.ImageIO;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

/**
 * 生成验证码,并把验证码存储在会话域中
 */
@WebServlet(urlPatterns = "/Encode")
public class EncodeServlet extends HttpServlet {

    // 写一个方法随机获取颜色
    public Color randomColor() {
        // r g b 取值范围 0到255
        Random random = new Random();
        return new Color(
                random.nextInt(256),
                random.nextInt(256),
                random.nextInt(256));
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }
    
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 创建缓存图片:指定宽width=90,高 height=30
        int width = 90;
        int height = 30;
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        // 获取画笔对象
        Graphics g = image.getGraphics();
        // 设置画笔颜色,并且填充矩形区域
        g.setColor(Color.white);
        g.fillRect(0, 0, width, height);
        // 创建可变字符串
        StringBuilder sb = new StringBuilder();
        // 从字符数组中随机得到字符,根据需求添加你需要的字符
        char[] arr = {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
                'A', 'B', 'C', 'D', 'N', 'E', 'W', 'b', 'o', 'y'};
        // 创建随机对象
        Random r = new Random();
        for (int i = 0; i < 4; i++) {
            // 随机产生一个索引值
            int index = r.nextInt(arr.length);
            // 根据索引获得随机字符
            char ch = arr[index]; 
            // 拼接字符
            sb.append(ch);
            // 设置字体,大小为 18
            g.setFont(new Font(Font.DIALOG, Font.BOLD + Font.ITALIC, 18));
            // 设置字的颜色随机
            g.setColor(randomColor());

            // 绘制字符串
            // 7. 将每个字符画到图片上,位置:
            int x = 5 + (i * 20);
            int y = 20;
            g.drawString(String.valueOf(ch), x, y);
        }
        // 将验证码字符串存储会话域中
        HttpSession session = request.getSession();
        session.setAttribute("verCode", sb.toString());
        // 8. 画10条干扰线,线的位置是随机的,x 范围在 width 之中,y 的范围在 height 之中。
        for (int i = 0; i < 10; i++) {
            // 设置颜色随机
            g.setColor(randomColor());
            int x1 = r.nextInt(width + 1);
            int x2 = r.nextInt(height + 1);
            int y1 = r.nextInt(width + 1);
            int y2 = r.nextInt(height + 1);
            g.drawLine(x1, y1, x2, y2);
        }
        // 9. 将缓存的图片输出到响应输出流中
        ImageIO.write(image, "png", response.getOutputStream());
    }
}

这样写完之后,我们前端页面只需要把img标签的src地址写成我们servlet的地址就可以实现验证码了。而之前的servlet也只需要根据相应的标签获取页面的验证码,再去获取会话域中的存放的正确验证码即可,由于还要实现自动登录,一会儿一起放最终结果好了。

5.修改前端页面,添加验证码和自动登录按钮

前面已经把主要功能实现了,那么接下来就是随便修改一下页面就好了,如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>login</title>
    <style>
        body {
            margin-top: 20px;
            margin: 0 auto;
        }
        .carousel-inner .item img {
            width: 100%;
            height: 300px;
        }
        .container .row div {
            /* position:relative;
            float:left; */
        }
        font {
            color: #666;
            font-size: 22px;
            font-weight: normal;
            padding-right: 17px;
        }
    </style>
</head>
<body>
<div class="container" style="width:100%;height:460px;">
    <div class="row">
        <div class="col-md-5">
            <div style="width:440px;border:1px solid #E7E7E7;padding:20px 0 20px 30px;border-radius:5px;margin-top:60px;background:#fff;">
                <form id="loginForm" class="form-horizontal" action="Login" method="post">

                    <div class="form-group">
                        <label for="username" class="col-sm-2 control-label">用户名</label>
                        <div class="col-sm-6">
                            <!--表单要加上name属性,否则服务器得到不值-->
                            <input type="text" class="form-control" name="username" id="username" placeholder="请输入用户名">
                        </div>
                    </div>
                    <div class="form-group">
                        <label for="password" class="col-sm-2 control-label">密码</label>
                        <div class="col-sm-6">
                            <input type="password" class="form-control" name="password" id="password"
                                   placeholder="请输入密码">
                        </div>
                    </div>

                    <div class="form-group">
                        <label for="verCode" class="col-sm-2 control-label">验证码</label>
                        <div class="col-sm-3">
                            <input type="text" class="form-control" name="verCode" id="verCode" placeholder="请输入验证码">
                        </div>
                        <div class="col-sm-3">

                            <img src="Encode" style="width: 90px; height: 30px; cursor: pointer;"
                                 onclick="changeImage(this)"
                                 title="看不清,点击刷新">
                        </div>
                    </div>
                    <div class="form-group">
                        <div class="col-sm-offset-2 col-sm-10">
                            <div class="checkbox">
                                <label>
                                    <input name="remember" type="checkbox"> 自动登录
                                </label>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
                            </div>
                        </div>
                    </div>
                    <div class="form-group">
                        <div class="col-sm-offset-2 col-sm-10">
                            <input id="click" type="submit" width="100" value="登录" name="submit" border="0"
                                   style="  eight:35px;width:100px;">
                        </div>
                    </div>
                </form>
            </div>
        </div>
    </div>
</div>
</body>
</html>

这样一个比较有代表性的框就有了,只需要实现功能就可以了。

6.实现自动登录

要想实现自动登录,那么就要明白自动登录是用什么实现的。

cookie这是唯一一个存在用户浏览器的一组数据,所以想要实现自动登录,就只能通过cookie来实现,完成这一步的时候,如果浏览器禁用了cookie,记得解除。

那么如何实现登录,其实就是在用户请求数据,服务器返回响应的时候,把用户名和密码以cookie的形式返回给客户端,这样下次登陆的时候,就只需要在前端页面编写js脚本实现读取cookie和自动发起请求即可实现。

但是我们现在多了一个验证码呀,这可怎么办呢?

其实也很简单,思路就是:

在cookie中多添加一个验证码的cookie,内容输入为不可能出现的验证码,这样用户在自己输入的时候就不会那样输入,而你又可以实现自动登陆了。

这样实现就可以了吗?

一般情况下是可以了,但是架不住有些小伙伴神通广大呀,想要更强力的杜绝,最好是把验证码框的内容长度也给定死了,在我们脚本读取cookie的时候,在手动修改长度,这样验证码可以任意长度任意字符串,就可以杜绝大部分小伙伴了,毕竟它不知道你的真实验证码是什么。

那么接下来,我们来实现自动登陆中servlet的编写,也顺便把验证码的判断加入进去:

package com.ps.Servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;

@WebServlet(urlPatterns = "/Login")
public class LoginServlet extends HttpServlet {

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

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.获取数据
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String remember = request.getParameter("remember");
        String code = request.getParameter("verCode");
        //2.获取会话域中的验证码
        HttpSession session = request.getSession();
        String encode = (String) session.getAttribute("verCode");
        //3.判断验证码是否通过,记住密码的,或者是输入验证码正确的
        if (code.equals(encode) || code.equals("remember")) {
            //4.验证码输入正确,判断输入的信息是否正确
            if ("admin".equals(username) && "123456".equals(password)) {
                //6.输入的信息正确,查看是否需要记住账号和密码
                if (remember != null) {
                    //8.需要记住账号和密码实现自动登录,创建cookie
                    Cookie uCookie = new Cookie("username", username);
                    uCookie.setMaxAge(6000);
                    response.addCookie(uCookie);

                    Cookie pCookie = new Cookie("password", password);
                    pCookie.setMaxAge(6000);
                    response.addCookie(pCookie);

                    Cookie codeCookie = new Cookie("verCode", "remember");
                    codeCookie.setMaxAge(600);
                    response.addCookie(codeCookie);
                }
                //9.把登录后的信息存储在会话域中,方面访问别的页面使用
                session.setAttribute("username", username);
                //10.跳转到index页面
                response.sendRedirect("index.jsp");
            } else {
                //7.输入的信息错误,跳回到原页面,需要重新输入
                request.getRequestDispatcher("login.html").forward(request, response);
            }
        } else {
            //5.验证码输入不正确,需要重新输入
            request.getRequestDispatcher("login.html").forward(request, response);
        }
    }
}

写到这里大部分小伙伴就发现了,哎好像后台该实现的都实现了,前端页面的按钮啥的也都有了,那是不是可以用了?其实还不可以,还有一些脚本没有编写,那么最后一步就是脚本的编写了

7.前端脚本编写:读取cookie并实现验证的点击切换

你看就这么简单就到最后一步了,前端页面脚本的编写其实没那么难,那么我们就先来实现一下验证码的点击切换功能。

看过之前页面的小伙伴一定还记得,我在img标签上加入了onclick属性,并写了一个函数名,那么我们就以那个函数名来编写一下,切换函数:

<script>
        function changeImage(img) {
        	//给对应的servlet发送请求,并添加输入值
        	//如果不添加输入值,会让服务器认为你在重复请求
        	//认为你请求的时间太短了,不需要响应,进而使用本地数据缓存
        	//导致验证码点击切换失败
            img.src = "Encode?t=" + Math.random();
        }
</script>

看了上面的脚本,非常的简单是吧,确实是,那么我们在一鼓作气把读取cookie的也写了吧。

<script>
	//如果你的脚本放在页面的最开始就一定要加入这个函数
	//不然你写的脚本就无法运行了
    window.onload = function () {
        // 读取Cookie信息
        var cookies = document.cookie;
        // 如果cookie不为空
        if (cookies) {
            // 得到用户名、密码和验证码
            // 其实就是一组键值对,根据你设置好的来就可以了
            var username = getCookie("username"); 
            var password = getCookie("password"); 
            var code = getCookie("verCode");
            // 填写相应的数值
            document.getElementById("username").value = username;
            document.getElementById("password").value = password;
            document.getElementById("verCode").value = code;
            // 提交表单
            document.getElementById("click").click();
        }
    };

	//获取cookie的值
    function getCookie(cname) {
    	//由于读取的cookie是通过;来分割的,所以需要根据;来获取对应的参数
        var ca = document.cookie.split(';'); 
        for (var i = 0; i < ca.length; i++) {
            var c = ca[i]; 
            var arr = c.split("="); 
            //这里一定要加入trim,这个很重要
            //为什么呢?因为cookie会在其中加入一些空格
			//去掉空格之后才能获取到正确的数值
            if (arr[0].trim() == cname) { 
                return arr[1];
            }
        }
        return "";
    }
</script>

写到这里,内容基本就写完了,接下来就该测试一下代码了:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
反复进入登录页面,哎,验证码登录和自动登录都实现了。

你学会了吗?

8.小结

那么我们象征性的小结一下吧。

如何实现自动登录:

1.在前端页面设置自动登录按钮
2.servlet获取是否要自动登录
3.自动登录则返回cookie给浏览器,让浏览器保存
4.编写脚本来帮助我们自动填写cookie中的数据

如何实现验证码:

1.编写能生成验证的servlet(不会写没关系,直接复制就好)
2.在前端页面加入img标签,并把src路径写成生成验证码的servlet的路径
3.设置name属性,便于后台servlet获取数据
4.编写脚本函数实现点击刷新验证码

如何同时实现验证和自动登录:

1.设定一个字符串为自动登录时的验证码
2.把这个字符串设置成cookie,并返回给浏览器
3.脚本实现自动登录的时候,把设置的字符串输入进去
4.当servlet判断到验证码是设置好的验证码时,放行,直接去判断用户名和密码是否正确

  • 4
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值