Jsp+Servlet+tomcat实现简单的登录验证码案例

首先声明这个案例是我白嫖的,但是嫖到一半发现代码不全,所以就自己就完善了案例代码!希望后续的小狐伴们不要碰到这个坑!!!

话不多说先看效果图:

这是登录首页:(这个案例其实很简陋,但是为了和你们分享,首页我还是花了一段时间修改的!)

 这是登录成功后的界面:

说实话真的很丑!!!但是别急,作为java后台人员我们不追求这个,我们追求的是技术,是可以买到面包和爱情的技术!来看下面的案例代码结构!!

 

上面是实现怎个案例的所有文件,本来应该按照MVC的框架放包的,但是怕和我一样的小白头晕,所以就简化了!不懂得可以私聊我哦!虽然我也不是很懂!接下来我们一个个分析上面的文件!我们先从视图层开始分享吧!(为什么不是说前端页面呢!因为最近了解到jsp实质还是java,请看下面我随便找到的一篇“高质量博客,博主也是这么认为的呢!)

 

index.jsp

<%-- Created by IntelliJ IDEA. --%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Login</title>
    <script>
        /*分析:
            点击超链接或者图片,需要换一张
            1.给超链接和图片绑定单击事件
            2.重新设置图片的src属性值

            PS:生成的图片先要缓存在本地,每次请求是不会修改,所以验证码图片不会切换;
            * 将图片路径后添加时间戳,通过错误的路径来欺骗服务器重新请求
         */

        window.onload = function () {
            //1.获取图片对象
            var img = document.getElementById("checkCode");
            //2.绑定图片单击事件
            img.onclick = function () {
                //加时间戳
                var date = new Date().getTime();
                //加时间戳,防止浏览器利用缓存
                img.src = "/VerificationCode?" + date;
            }

            //绑定链接点击事件
            var ahref = document.getElementById("change");
            ahref.onclick = function () {
                var date = new Date().getTime();
                img.src = "/VerificationCode?" + date;
            }
        }
    </script>

    <style>
        body {
            /* 不重复 */
            background: url("img/backgroundimg2.jpg") no-repeat;
            /* 背景铺满 */
            background-size: 100% auto;
        }
        div {
            color: red;
        }
        #login-box {
            width: 30%;
            height: auto;
            /* 居中 */
            margin: 0 auto;
            /* 中央位置 */
            margin-top: 15%;
            /* 内容居中 */
            text-align: center;
            background: #00000080;
            padding: 20px 50px;
        }

        #login-box h1 {
            color: #fff;
        }

        #login-box .form .item {
            margin-top: 15px;
        }

        #login-box .form .item i {
            font-size: 18px;
            color: #fff;
        }

        /* input border */
        #login-box .form .item input {
            width: 180px;
            font-size: 18px;
            border: 0;
            border-bottom: 2px solid #fff;
            padding: 6px 10px;
            background: #ffffff00;
            color: #fff;
        }

        #login-box .button {
            margin-top: 15px;
            width: 180px;
            height: 30px;
            font-size: 20px;
            font-weight: 700;
            color: #fff;
            background-image: linear-gradient(120deg, #84fab0 0%, #8fd3f4 100%);
            /* background-image: linear-gradient(to top, #a8edea 0%, #fed6e3 100%); */
            border: 0;
            border-radius: 15px;
        }
    </style>
</head>
    <body>
        <form class="box" action="${pageContext.request.contextPath}/ServletLogin" method="POST">
            <div id="login-box">
                <h1>Login</h1>
                <!-- 输入框 -->
                <div class="form">
                    <div class="item">
                        <i class="fa fa-user-circle-o" aria-hidden="true"></i>
                        <input type="text" name="username" placeholder="Username">
                    </div>
                    <div class="item">
                        <i class="fa fa-key" aria-hidden="true"></i>
                        <input type="password" name="password" placeholder="Password">
                    </div>
                    <div class="item">
                        <i class="fa fa-check-circle-o" aria-hidden="true"></i>
                        <input type="text" name="checkCode" placeholder="验证码">
                    </div>
                    <div><br>
                        <img id="checkCode" src="${pageContext.request.contextPath}/VerificationCode" alt="checkCode">
                        <a id="change" href="">看不清?换一张</a>
                    </div>
                </div>
                <input type="submit" class="button" value="Login">
            </div>
        </form>
        <div ><%=request.getAttribute("CHECKCODE_Error")==null ? "" : request.getAttribute("CHECKCODE_Error")%></div>
        <div><%=request.getAttribute("Login_Error")==null ? "" : request.getAttribute("Login_Error")%></div>
    </body>
</html>
backgroundimg.jpg
index视图层背景图

 

背景图我都给你准备好了,你看我就差拿着你的手敲代码了!

success.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <style type="text/css">
        body{
            background: url("img/success.jpg") no-repeat;
            background-size: 100% auto;
        }
    </style>
</head>
<body>
<h1>sucesss</h1>
</body>
</html>

这个成功视图层我不想写,就放了一张背景图,关于登录成功背景图似乎有点少,还很丑!真的丑。。。。

success.jpg
​​登陆成功背景图

背景图给你们了,总不要说我小气了吧!还有一个背景图好丑又模糊,我就不给你们了,反正也没什么用!

关于web.xml是没有任何代码配置的!对于新手的话我挺建议走web.xml依赖注入的!但是我这次没用,就下次用吧!

来看servlet代码类:
ServletLogin.java
package com.dsw.varification;

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.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;

/**
 * @author Vere
 */
@WebServlet(name ="ServletLogin",urlPatterns = "/ServletLogin")
public class ServletLogin extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.设置编码
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=UTF-8");
        String verification = req.getParameter("checkCode");

        //2.获取所有请求参数
        String username = req.getParameter("username");
        String password = req.getParameter("password");

        User loginUser = new User(username,password);
        //4.验证码处理
        //4.1获取生成的验证码
        HttpSession session = req.getSession();
        String validation_code = (String) session.getAttribute("validation_code");
        //删除session中存储的验证码,防止重复使用
        session.removeAttribute("validation_code");
        //4.2判断验证码是否正确
        if (validation_code != null && validation_code.equalsIgnoreCase(verification)) {
            //忽略大小写,比较字符串,验证码正确
            User user = new User(username,password);
            //判断用户名和密码是否一致
            //5.调用UserDao的login方法

            //6.判断user
            if ("admin".equals(username)&&"root".equals(password)) {
                //登陆成功,存储数据
                req.setAttribute("user", user);
                session.setAttribute("username", user.getName());
                //转发
                req.getRequestDispatcher("/successServlet").forward(req, resp);

            }else {
                //登录失败
                req.getRequestDispatcher("/failServlet").forward(req, resp);
            }
        }else {
            //验证码不一致
            //存储提示信息到request
            req.setAttribute("CHECKCODE_Error", "验证码错误");
            //转发到登录页面
            req.getRequestDispatcher("index.jsp").forward(req, resp);
        }
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }
}

 

上课了,看黑板!关于下面这个注释能看懂吗?

@WebServlet(name ="ServletLogin",urlPatterns = "/ServletLogin")
不懂得看下面,能的也要看下面,你以为你很牛逼吗?
属性名类型描述
nameString指定Servlet 的 name 属性,等价于 <servlet-name>。如果没有显式指定,则该 Servlet 的取值即为类的全限定名。
valueString[]该属性等价于 urlPatterns 属性。两个属性不能同时使用。
urlPatternsString[]指定一组 Servlet 的 URL 匹配模式。等价于<url-pattern>标签。
loadOnStartupint指定 Servlet 的加载顺序,等价于 <load-on-startup>标签。
initParamsWebInitParam[]指定一组 Servlet 初始化参数,等价于<init-param>标签。
asyncSupportedboolean声明 Servlet 是否支持异步操作模式,等价于<async-supported> 标签。
descriptionString该 Servlet 的描述信息,等价于 <description>标签。
displayNameString该 Servlet 的显示名,通常配合工具使用,等价于 <display-name>标签。

主要是看name和urlPatterns这两个属性!

在Servlet中,设置了@WebServlet注解,当请求该Servlet时,服务器就会自动读取当中的信息,如果注解@WebServlet("/ServletLogin"),则表示该Servlet默认的请求路径为…/ServletLogin,这里省略了urlPatterns属性名,完整的写法应该是:@WebServlet(urlPatterns = “/ServletLogin”),如果在@WebServlet中需要设置多个属性,必须给属性值加上属性名称,中间用逗号隔开,否则会报错.
若没有设置@WebServlet的name属性,默认值会是Servlet的类完整名称.

在servlet3.0以后,web.xml中对Servlet配置,同样可以在@WebServlet注解中配置.

req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=UTF-8");

如果你和我一样害怕页面乱码!请乖乖加上这个代码,好吗?不要动不动就说“哎呀!我的怎么乱码了?”呵呵哒!比我还菜,菜鸡......

 //2.获取所有请求参数
   String username = req.getParameter("username");
   String password = req.getParameter("password");

你们谁敢说这个看不懂的?我,我看不懂,其实之前我也看不懂,不过我最近学了《葵花宝典》,我豁然开朗,竟然看懂了,

String getParameter(String name):根据参数名称获取参数值

例如例子中index.jsp中from标签传递的参数为“username”和“password”,所以最后在java程序中获得的也是username和password的值
下面是一些还没用到的方法也是关于

String[] getParameterValues(String name);//根据参数名称获取参数值的数组 hobby=xx&hobby=game


Enumeration getParameterNames();//获取所有请求的参数名称


Map<String,String[]> getParameterMap();//获取所有参数的map集合

本人不建议使用Map<String,String[]> getParameterMap():

然后就是关于session这个知识点了

HttpSession session = req.getSession();
String validation_code = (String) session.getAttribute("validation_code");
//删除session中存储的验证码,防止重复使用
session.removeAttribute("validation_code");

我很好奇你掌握了session?你个菜鸡,拽什么拽,反正我不会,这是我找的笔记:活不多说这是我白嫖的,写的挺好的,喜欢的可以点进去看原文Session原理

Web三大概念:cookie,session,application

Session:记录一系列状态

Session与cookie功能效果相同。Session与Cookie的区别在于Session是记录在服务端的,而Cookie是记录在客户端的。

解释session:当访问服务器否个网页的时候,会在服务器端的内存里开辟一块内存,这块内存就叫做session,而这个内存是跟浏览器关联在一起的。这个浏览器指的是浏览器窗口,或者是浏览器的子窗口,意思就是,只允许当前这个session对应的浏览器访问,就算是在同一个机器上新启的浏览器也是无法访问的。而另外一个浏览器也需要记录session的话,就会再启一个属于自己的session

原理:HTTP协议是非连接性的,取完当前浏览器的内容,然后关闭浏览器后,链接就断开了,而没有任何机制去记录取出后的信息。而当需要访问同一个网站的另外一个页面时(就好比如在第一个页面选择购买的商品后,跳转到第二个页面去进行付款)这个时候取出来的信息,就读不出来了。所以必须要有一种机制让页面知道原理页面的session内容。

session的两种实现方式(也就是传递方式):第一种通过cookies实现。第二种通过URL重写来实现

第一种方式的理解:就是把session的id 放在cookie里面(为什么是使用cookies存放呢,因为cookie有临时的,也有定时的,临时的就是当前浏览器什么时候关掉即消失,也就是说session本来就是当浏览器关闭即消失的,所以可以用临时的cookie存放。保存再cookie里的sessionID一定不会重复,因为是独一无二的。),当允许浏览器使用cookie的时候,session就会依赖于cookies,当浏览器不支持cookie后,就可以通过第二种方式获取session内存中的数据资源。

第二种方式的理解:在客户端不支持cookie的情况下使用。为了以防万一,也可以同时使用。

如果不支持cookie,必须自己编程使用URL重写的方式实现。

   如何重写URL:通过response.encodeURL()方法

      encodeURL()的两个作用

         第一个作用:转码(说明:转中文的编码,或者一些其他特殊的编码。就好比如网页的链接中存在中文字符,就会转换成为一些百分号或者其他的符号代替。)

第二个作用:URL后面加入sessionID,当不支持cookie的时候,可以使用encodeURL()方法,encodeUTL()后面跟上sessionID,这样的话,在禁用cookie的浏览器中同时也可以使用session了。但是需要自己编程,只要链接支持,想用session就必须加上encodeURL()。

 

Session中的一些常用方法说明

isNew():是否是新的Session,一般在第一次访问的时候出现

getid():拿到session,获取ID

getCreationTime():当前session创建的时间

getLastAccessedTime():最近的一次访问这个session的时间。

getRrquestedSessionid: 跟随上个网页cookies或者URL传过来的session

isRequestedSessionIdFromCookie():是否通过Cookies传过来的

isRequestedSessionIdFromURL():是否通过重写URL传过来的

isRequestedSessionIdValid():是不是有效的sessionID

session有期限

 

当一个网站的第一个窗口关掉了,而没有继续接着访问第二个页面,就没有使用到session。那么session会在中断程序后立刻关闭session吗?这个时候session就需要给它保留的时间,当最近一次访问的时候开始计时,每刷新一次重写开始计时。当隔了这么久的时间,没有访问这个session后,对不起,要关闭这个session了。session有过期时间,session什么时候过期,要看配置,

session能干什么

session就是服务器里面的一块内存,内存里面能放任何东西,只要是名值对就可以了。

session里面的名字永远都是String类型

 

这个代码还有一个知识点就是

req.getRequestDispatcher("/successServlet").forward(req, resp);

可是我不想讲了,太累了,怕你们嫌弃我啰嗦......

请求转发和重定向的区别

转发:

转发
​​​​​​

重定向:

重定向

User.java

package com.dsw.varification;

/**
 * @author Vere
 */
public class User {
    private String name;
    private String password;

    public User() {
    }

    public User(String name, String password) {
        this.name = name;
        this.password = password;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

这个没有讲头了!下一个

SuccessServlet.java
package com.dsw.varification;

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 java.io.IOException;

/**
 * @author Vere
 */
@WebServlet(name = "SuccessServlet",urlPatterns = "/successServlet")
public class SuccessServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //页面设置编码
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=UTF-8");
        //获取request域中共享的user对象
        User user= (User)req.getAttribute("user");

        if(user != null) {
            //重定向到success.jsp
            resp.sendRedirect(req.getContextPath() + "/success.jsp");
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

下一个

FailServlet.java 
package com.dsw.varification;

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 java.io.IOException;

/**
 * @author Vere
 */
@WebServlet(name = "FailServlet" ,urlPatterns = "/failServlet")
public class FailServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //页面设置编码
        resp.setContentType("text/html;charset=UTF-8");
        req.setAttribute("Login_Error", "用户名或密码错误");
        //输出
        resp.getWriter().write("登陆失败...用户名或密码错误");
        req.getRequestDispatcher("/index.jsp").forward(req, resp);
    }
}

注意!!!注意!!!这个要考的,快拿出笔记本出来:

VerificationCode.java 
package com.dsw.varification;

import javax.imageio.ImageIO;
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.io.OutputStream;
import java.util.Random;

/**
 * @author Vere
 */
@WebServlet(name = "VerificationCode",urlPatterns = {"/VerificationCode"})
public class VerificationCode extends HttpServlet {
    private static final String codeChars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 获得验证码集合的长度
        int charsLength = codeChars.length();
        // 下面3条记录是关闭客户端浏览器的缓冲区

        // 这3条语句都可以关闭浏览器的缓冲区,但是由于浏览器的版本不同,对这3条语句的支持也不同

        // 因此,为了保险起见,同时使用这3条语句来关闭浏览器的缓冲区
        resp.setHeader("ragma", "No-cache");
        resp.setHeader("Cache-Control", "no-cache");
        resp.setDateHeader("Expires", 0);

        // 设置图形验证码的长和宽
        int width = 100, height = 30;
        BufferedImage image = new BufferedImage(width, height,
                BufferedImage.TYPE_INT_RGB);
        Graphics g = image.getGraphics();
        Random random = new Random();
        g.setColor(getRandomColor(180, 250));

        g.fillRect(0, 0, width, height);

        g.setFont(new Font("Times New Roman", Font.ITALIC, height));

        g.setColor(getRandomColor(120, 180));
        // 用户保存最后随机生成的验证码
        StringBuffer validationCode = new StringBuffer();
        // 验证码的随机字体
        String[] fontNames = { "Times New Roman", "Book antiqua", "Arial" };

        // 随机生成4个验证码
        for (int i = 0; i < 5; i++) {
            // 随机设置当前验证码的字符的字体
            g.setFont(new Font(fontNames[random.nextInt(3)], Font.ITALIC,
                    height));
            // 随机获得当前验证码的字符
            char codeChar = codeChars.charAt(random.nextInt(charsLength));
            validationCode.append(codeChar);
            // 随机设置当前验证码字符的颜色
            g.setColor(getRandomColor(10, 100));
            // 在图形上输出验证码字符,x和y都是随机生成的
            g.drawString(String.valueOf(codeChar), 16 * i + random.nextInt(7),
                    height - random.nextInt(6));
        }

        // 获得HttpSession对象

        HttpSession session = req.getSession();

        // 设置session对象5分钟失效

        session.setMaxInactiveInterval(5 * 60);

        // 将验证码保存在session对象中,key为validation_code

        session.setAttribute("validation_code", validationCode.toString());
        //关闭Graphics对象
        g.dispose();

        OutputStream outS = resp.getOutputStream();

        ImageIO.write(image, "JPEG", outS);

    }

    private Color getRandomColor(int minColor, int maxColor) {
        Random random = new Random();
        if(minColor > 255){
            minColor = 255;
        }
        if(maxColor > 255){
            maxColor = 255;
        }
        //获得r的随机颜色值
        int red = minColor+random.nextInt(maxColor-minColor);
        int green = minColor + random.nextInt(maxColor-minColor);
        int blue = minColor + random.nextInt(maxColor-minColor);
        return new Color(red,green,blue);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

好了,讲完了!关于源码

  • 4
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值