过滤器Filter(二)

完成自动登录案例

用户以及验证码校验

步骤

  1. 从后台完成验证码的代码生成,同时将验证码对应文本写入session域中
  2. 完成前台登录页面,用户访问登录页面,session域设定好用户对应的验证码文本
  3. 用户写入验证码,当鼠标焦点离开input框,发送Ajax请求,携带用户输入内容
  4. 对用户输入验证码进行校验,验证码正确与否作出相应响应
  5. 当点击登录按钮时,触发校验用户名以及密码事件,通过Ajax将用户名以及密码传递给登录servlet,进行数据库查询
  6. 返回查询结果,结果存在与否作出相应相应

导入相应jar包

自动生成验证码图片工具

package com.company.utils;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;

import javax.imageio.ImageIO;


public class VerifiCode {

    private int weight = 100;             //验证码图片的长和宽
    private int height = 50;
    private String text;                //用来保存验证码的文本内容
    private Random r = new Random();      //获取随机数对象
    private String[] fontNames = {"宋体", "华文楷体", "黑体", "微软雅黑", "楷体_GB2312"};   //字体数组

    private Color randomColor()          //获取随机的颜色
    {
        int r = this.r.nextInt(150);        //这里为什么是150,因为当r,g,b都为255时,即为白色,为了好辨认,需要颜色深一点。
        int g = this.r.nextInt(150);
        int b = this.r.nextInt(150);
        return new Color(r, g, b);          //返回一个随机颜色
    }

    private Font randomFont()              //获取随机字体
    {
        int index = r.nextInt(fontNames.length);      //获取随机的字体
        String fontName = fontNames[index];
        int style = r.nextInt(4);            //随机获取字体的样式,0是无样式,1是加粗,2是斜体,3是加粗加斜体
        int size = r.nextInt(5) + 24;              //随机获取字体的大小
        return new Font(fontName, style, size);   //返回一个随机的字体
    }

    private char randomChar()           //获取随机字符
    {
        String codes = "23456789abcdefghjkmnopqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ";
        int index = r.nextInt(codes.length());
        return codes.charAt(index);
    }

    private void drawLine(BufferedImage image)             //画干扰线,验证码干扰线用来防止计算机解析图片
    {
        int num = 3;                                         //定义干扰线的数量
        Graphics2D g = (Graphics2D) image.getGraphics();
        for (int i = 0; i < num; i++) {
            int x1 = r.nextInt(weight);
            int y1 = r.nextInt(height);
            int x2 = r.nextInt(weight);
            int y2 = r.nextInt(height);
            g.setColor(randomColor());
            g.drawLine(x1, y1, x2, y2);
        }
    }

    private BufferedImage createImage()           //创建图片的方法
    {
        BufferedImage image = new BufferedImage(weight, height, BufferedImage.TYPE_INT_RGB); //创建图片缓冲区
        Graphics2D g = (Graphics2D) image.getGraphics();     //获取画笔
        g.setColor(Color.GRAY);                 //设置背景色
        g.fillRect(0, 0, weight, height);
        return image;                           //返回一个图片
    }

    public BufferedImage getImage()             //获取验证码图片的方法
    {
        BufferedImage image = createImage();
        Graphics2D g = (Graphics2D) image.getGraphics();     //获取画笔
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 4; i++)                    //画四个字符即可
        {
            String s = randomChar() + "";                           //随机生成字符,因为只有画字符串的方法,没有画字符的方法,所以需要将字符变成字符串再画
            sb.append(s);                                  //添加到StringBuilder里面
            float x = i * 1.0F * weight / 4;                     //定义字符的x坐标
            g.setFont(randomFont());                      //设置字体,随机
            g.setColor(randomColor());                    //设置颜色,随机
            g.drawString(s, x, height - 5);
        }
        this.text = sb.toString();
        drawLine(image);
        return image;
    }

    public String getText()                             //获取验证码文本的方法
    {
        return text;
    }

    public static void output(BufferedImage image, OutputStream out) throws IOException                  //将验证码图片写出的方法
    {
        ImageIO.write(image, "JPEG", out);
    }
}

验证码传输servlet

package com.company.web.servlet;

import com.company.utils.VerifiCode;

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

@WebServlet(name = "captcha", urlPatterns = "/captcha")
public class CaptchaServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

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


        //        0.获取session对象
        HttpSession session = request.getSession();

        //        1.获取验证码图片以及验证码文本
        VerifiCode verifiCode = new VerifiCode();
        BufferedImage image = verifiCode.getImage();
        String text = verifiCode.getText();
        session.setAttribute("captcha",text.toLowerCase());

        //        2.将验证码图片输出
        VerifiCode.output(image, response.getOutputStream());
    }
}

编写登录html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
    <link rel="stylesheet" href="../css/index.css">


</head>
<body>
<div id="wrap">
    <div id="top-bg">
    </div>
    <div id="header">
        <h1 id="logo-text"><a href="index.html" title="">泰格<span>♥个人博客</span></a></h1>
        <p id="slogan">一个技术分享,共同学习、交流的个人技术博客</p>
        <div id="header-links">
            <p>
                <a href="index.html">Home</a> |
                <a href="register.html">注册</a> |
                <a href="login.html">登录</a>
            </p>
        </div>
    </div>
    <div id="header-photo"></div>
    <!--登录页面-->
    <div id="login">
        <div id="out_form_1">
            <div id="form_title">
                <div id="form_head_1">
                    请输入用户名和密码
                </div>
            </div>
            <form action="/login" id="register_1" method="post">
                <div class="form_group">
                    <div class="name_label">
                        用户名
                    </div>
                    <label>
                        <input class="input_block" type="text" name="username"
                               placeholder="请输入正确的用户名">
                        <span id="username">
                        </span>
                    </label>
                </div>

                <div class="form_group">
                    <div class="name_label">密码</div>
                    <label><input type="password" class="input_block" name="password"
                                  placeholder="请输入密码"></label>
                </div>

                <div id="captcha">
                    <div class="text">验证码</div>
                    <div class="input1">
                        <input type="text" id="captcha-input" name="captcha" placeholder="输入验证码">
                        <div id="hidden" style="padding: 0;width: 97px">
                        </div>
                    </div>
                    <div class="image">
                        <img src="/captcha" alt="">
                        <div style="cursor: pointer">
                            看不清?点击刷新
                        </div>
                    </div>
                </div>

                <div class="form_group" style="color: black;padding-left: 138px;font-size: 12px;">
                    下次自动登录&nbsp;<input type="checkbox" style="width: 15px;height: 15px;" name="autoLogin" value="true">
                </div>

                <div style="clear: both "></div>

                <div class="form_group">
                    <div class="name_label"></div>
                    <input type="submit" class="btn" value="登录" id="submit" style="cursor:pointer">
                </div>
            </form>
        </div>
    </div>
    <!-- footer starts -->
    <div id="footer-wrap">
        <div id="footer-columns">

            <div class="col3">
                <h3>Tincidunt</h3>
                <ul>
                    <li><a href="index.html">consequat molestie</a></li>
                    <li><a href="index.html">sem justo</a></li>
                    <li><a href="index.html">semper</a></li>
                    <li><a href="index.html">magna sed purus</a></li>
                    <li><a href="index.html">tincidunt</a></li>
                </ul>
            </div>

            <div class="col3-center">
                <h3>Sed purus</h3>
                <ul>
                    <li><a href="index.html">consequat molestie</a></li>
                    <li><a href="index.html">sem justo</a></li>
                    <li><a href="index.html">semper</a></li>
                    <li><a href="index.html">magna sed purus</a></li>
                    <li><a href="index.html">tincidunt</a></li>
                </ul>
            </div>

            <div class="col3">
                <h3>Praesent</h3>
                <ul>
                    <li><a href="index.html">consequat molestie</a></li>
                    <li><a href="index.html">sem justo</a></li>
                    <li><a href="index.html">semper</a></li>
                    <li><a href="index.html">magna sed purus</a></li>
                    <li><a href="index.html">tincidunt</a></li>
                </ul>
            </div>
            <!-- footer-columns ends -->
        </div>

        <div id="footer-bottom">

            <p>
                &copy; 2010 Your Company

                &nbsp;&nbsp;&nbsp;&nbsp;

                <a href="http://www.cssmoban.com/" title="Website Templates">website templates</a> from <a
                    href="http://www.cssmoban.com/">????</a>

                &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

                <a href="index.html">Home</a> |
                <a href="index.html">Sitemap</a> |
                <a href="index.html">RSS Feed</a> |
                <a href="http://validator.w3.org/check?uri=referer">XHTML</a> |
                <a href="http://jigsaw.w3.org/css-validator/check/referer">CSS</a>
            </p>

        </div>

        <!-- footer ends-->
    </div>
</div>
</body>
</html>

编写js代码完成登录校验

<script src="../js/jquery-2.1.0.js"></script>
<script>

    $(function () {
        // 登录按钮鼠标覆盖改变颜色
        let submit = $("#submit");

        submit.submit();

        submit.on("mouseover", function () {
            submit.css("background", "#1d15c9")
        });

        submit.on("mouseout", function () {
            submit.css("background", "#146dfc")
        });


        // 点击登录进行ajax校验
        submit.on("click", function () {
            flag = -1;
            $.ajax({
                type: "post",
                url: "/checkmes",
                async: false,
                data: {
                    // 表单将数据传输给服务器
                    "password": $("input[name=password]").val(),
                    "username": $("input[name=username]").val(),
                    "captcha": $("#captcha-input").val()
                },
                success: function (data) {
                    // 对data的result属性进行判断
                    if (data.result === true) {
                        // 验证通过标志位改为1
                        flag = 1;
                    } else {
                        // 验证不通过,显示错误信息
                        $("#hidden").html(data.result)
                    }
                },
                dataType: "json"
            });
            if (flag !== 1) {
                return false;
            }
        });
    });

    // 点击看不清刷新图片
    $(function () {
        // 1.定位图片
        $(".image div").click(function () {
            $(".image img").attr("src", "/captcha?time=" + new Date().getTime());
        })
    });
</script>

表单校验CheckMesServlet

package com.company.web.servlet;

import com.alibaba.fastjson.JSON;
import com.company.domain.User;
import com.company.service.AutoLoginService;
import org.apache.commons.beanutils.BeanUtils;
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.sql.SQLException;

@WebServlet(name = "checkmes", urlPatterns = "/checkmes")
public class CheckMesServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

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

        String Json;

        //        0.对数据进行转码
        response.setContentType("text/html;charset=utf-8");

        //        1.获取session对象
        HttpSession session = request.getSession();

        //        2.与请求发送的验证码文本进行对比,获取检验结果
        String captcha = (String) session.getAttribute("captcha");
        boolean b = captcha.equals(request.getParameter("captcha"));
        if (!b) {

            //        如果是假,返回false的json数据给浏览器
            Json = "{\"result\":\"验证码错误\"}";
            response.getWriter().write(Json);
        }

        //        3.将用户信息封装到JavaBean中
        User user = new User();
        try {
            BeanUtils.populate(user, request.getParameterMap());
        } catch (IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }

        boolean userBoolean = false;
        if (b) {
            //        4.告知service层判断用户是否在数据库
            try {
                userBoolean = new AutoLoginService().CheckUser(user);
            } catch (SQLException e) {
                e.printStackTrace();
            }

            //        5.根据判断返回给Ajax引擎数据
            if (!userBoolean) {
                Json = "{\"result\":\"用户名或密码错误\"}";
                response.getWriter().write(JSON.toJSONString(Json));
            }
        }

        //        如果都正确,返回验证通过
        if (b && userBoolean) {
            Json = "{\"result\":true}";
            response.getWriter().write(Json);
        }
    }
}

使用Ajax提交需注意

  1. 设置获取数据类型为json
    dataType: "json"
    
  2. 在后台要设置好响应编码
  3. 将ajax请求设置为同步,否则数据还没传到客户端时,后序代码就会执行
    async: false
    
  4. 单个按钮绑定多个事件要使用.on(“事件”,function(){})

自动登录

步骤

  1. 用户登录是否勾选自动登录,勾选—->4,没勾选—->5
  2. 完成监听器接口的实现类,并且作为封装数据的JavaBean
  3. 完成登录LoginServlet,包含处理用户指定自动登录以及非自动登录
  4. 自动登录:将数据序列化到JavaBean中,再将JavaBean存储到Session域,并且通过cookie设置在客户端保存时长无限
  5. 非自动登录,将数据封装到不需要session持久化的JavaBean中
  6. 将响应转发到首页
  7. 完成首页页面Ajax请求,要求获取当前session在服务器存储的JavaBean,并且通过Ajax引擎获取数据,进行局部刷新

图解

JavaBean(User)

package com.company.domain;

import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionEvent;
import java.io.Serializable;

/*
作为请求传递的数据的一个封装对象
 */
public class User implements Serializable,HttpSessionActivationListener{
    private String username;
    private String realName;
    private String email;
    private String password;
    private String company;
    private String telephone;
    private String UId;
    private String captcha;

    public String getUId() {
        return UId;
    }

    public void setUId(String UId) {
        this.UId = UId;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", realName='" + realName + '\'' +
                ", email='" + email + '\'' +
                ", password='" + password + '\'' +
                ", company='" + company + '\'' +
                ", telephone='" + telephone + '\'' +
                ", captcha='" + captcha + '\'' +
                '}';
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getRealName() {
        return realName;
    }

    public void setRealName(String realName) {
        this.realName = realName;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPassword() {
        return password;
    }

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

    public String getCompany() {
        return company;
    }

    public void setCompany(String company) {
        this.company = company;
    }

    public String getTelephone() {
        return telephone;
    }

    public void setTelephone(String telephone) {
        this.telephone = telephone;
    }

    public String getCaptcha() {
        return captcha;
    }

    public void setCaptcha(String captcha) {
        this.captcha = captcha;
    }

    @Override
    public void sessionWillPassivate(HttpSessionEvent httpSessionEvent) {
        System.out.println("我被钝化了");
    }

    @Override
    public void sessionDidActivate(HttpSessionEvent httpSessionEvent) {
        System.out.println("我被活化了");
    }
}

LoginServlet

package com.company.web.servlet;

import com.company.domain.ShortUser;
import com.company.domain.User;
import org.apache.commons.beanutils.BeanUtils;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;

@WebServlet(name = "login", urlPatterns = "/login")
public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

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

        //        0.解决编码问题,获取session对象
        request.setCharacterEncoding("utf-8");
        HttpSession session = request.getSession();

        //        1.判断用户是否需要进行自动登录
        boolean autoLogin = Boolean.valueOf(request.getParameter("autoLogin"));
        if (autoLogin) {

            //            2.用户需要自动登录,将用户信息序列化钝化到本地
            User user = new User();
            Map<String, String[]> parameterMap = request.getParameterMap();
            try {
                BeanUtils.populate(user, parameterMap);
            } catch (IllegalAccessException | InvocationTargetException e) {
                e.printStackTrace();
            }
            session.setAttribute("user", user);

            //            session持久化
            String id = session.getId();
            Cookie cookie = new Cookie("JSESSIONID", id);
            cookie.setMaxAge(1000 * 60 * 100);
            response.addCookie(cookie);
        } else {

            //            3.用户不需要自动登录,将用户信息封装到不需要session持久化的JavaBean中
            ShortUser shortUser = new ShortUser();
            shortUser.setUsername(request.getParameter("username"));
            session.setAttribute("user", shortUser);
        }

        //        4.转发到首页
        response.sendRedirect(request.getContextPath() + "/html/index.html");
    }
}

index.html(Ajax–js)

<script src="../js/jquery-2.1.0.js"></script>
<script>
    $(function () {

        // ajax请求向服务器请求数据
        $.ajax({
            url: "/showuser",
            type: "post",
            success: function (date) {
                if (date !== null) {

                    // 获取对象属性,并且将名字设置到全文
                    $("#user").html(date.username);
                    $("#exit").html("退出")
                }
            },
            dataType: "json"
        })
    })
</script>