JavaWeb验证码案例(Cookie & Session)

学习资料黑马java。

Cookie,主要用于用户无登入情况下的身份识别。

package cn.web.Cookie;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
/*
在服务器中的Servlet判断是否有一个名为lastTime的cookie
1. 有:不是第一次访问
  1. 响应数据:欢迎回来,您上次访问时间为:2018年6月10日11:50:20
  2. 写回Cookie:lastTime=2018年6月10日11:50:01
2. 没有:是第一次访问
  1. 响应数据:您好,欢迎您首次访问
  2. 写回Cookie:lastTime=2018年6月10日11:50:01
*/

@WebServlet("/cookieTest")
public class CookieTest extends HttpServlet {
    
    
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        response.setContentType("test/html;charset=utf-8");

        //1.获取cookie
        Cookie[] cookies = request.getCookies();
        //2.遍历cookie数组
        if (cookies != null && cookies.length > 0)
        {
    
    
            //输入iter则弹出快捷键
            for (Cookie cookie : cookies) {
    
    
                //3.获取cookie名称
                String name = cookie.getName();
                if("lastname".equals(name)) //有该数据,不是第一次访问
                {
    
    
                    //获取当前时间,并更新cookie
                    Date date = new Date();
                    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss");
                    String format = simpleDateFormat.format(date);//把date按格式排好
                    cookie.setValue(format); //传入cookie中,覆盖掉原来的值
                    //设置cookie存活时间
                    cookie.setMaxAge(60*60*24*30);
                    response.addCookie(cookie);

                    //响应数据,获取数据value值
                    String value = cookie.getValue();
                    response.getWriter().write("欢迎回来,您上次访问的时间是:"+value);

                    break;
                }
            }
        }
    }

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

案例:带验证码的登入界面

文件结构:
在这里插入图片描述
核心逻辑简述:
1.通过验证码生成Servlet生成一个验证码,并把正确的文本存在session中。
2.用户输入三个值,账号,密码,和验证码。
3.从request中get到这三个参数,并先用用户的验证码和session中存放的正确结果做对比。
3.1如果不对,则转发一个“验证码不对”的String到前端。
3.2如果正确,则开始判断用户名和密码。
4.把用户名和密码拿出来,通过连接池去数据库中查询。
5.如果找到了,则封装起来用户名和密码。如果没找到,则返回一个Null。
6.进行相应的跳转。

Login.jsp – 登入界面首页
有个小技巧 div中,如果想空的时候不显示,可以用三元运算符:

 <div> <%=request.getAttribute("cc_error") == null? "":request.getAttribute("cc_error")%></div>

此外,关于jsp中写java <%= xxxxx %>是不能有分号的,这就是一个单行的表达式。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Login</title>
    <script>
        //当窗口加载完,触发事件。
        window.onload = function () {
     
     
            //当id为img(就是下方的绑定的image)被点击,触发事件
            document.getElementById("img").onclick = function () {
     
     

                var date = new Date(); //加入时间戳 这样每次点击就是一次新访问了checkcode
                this.src="/day16/checkCodeServlet?time=" + date.getTime();
            }
        }
    </script>

    <style>
        div{
     
     
            color:red;
        }
    </style>

</head>
<body>
        <form action="/day16/loginServlet" method="post">
            <table>
                <tr>
                    <td>用户名</td>
                    <td><input type="text" name = "username"></td>
                </tr>
                <tr>
                    <td>密码</td>
                    <td><input type="password" name = "password"></td>
                </tr>
                <tr>
                    <td>验证码</td>
                    <td><input type="text" name = "checkcode"></td>
                </tr>

                <tr>
                    <td colspan="2"><img id="img" src="/day16/checkCodeServlet"></td>
                </tr>

                <tr>
                    <td>用户名</td>
                    <td><input type="submit" value = "登入"></td>
                </tr>
            </table>

        </form>

		
        <div> <%=request.getAttribute("cc_error") == null? "":request.getAttribute("cc_error")%></div>
        <div> <%=request.getAttribute("up_error")==null?"":request.getAttribute("cc_error")%></div>

</body>
</html>

CheckCodeServlet 用来生成img验证码
存储了随机生成的值在session中

package cn.web.Servlet;

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.util.Random;

@WebServlet("/checkCodeServlet")
public class CheckCodeServlet extends HttpServlet {
    
    
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        int width = 200;
        int height = 100;

        //1创建一个对象,在内存中是图片(验证码图片对象)
        BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);

        //2.美化图片
        //2.1填充背景色
        Graphics g = image.getGraphics();
        g.setColor(Color.pink);
        g.fillRect(0,0,width,height); //G.填充框

        //2.2画边框
        g.setColor(Color.black);
        g.drawRect(0,0,width-1,height-1);

        //2.3 写验证码
        //可能出现的字符库
        String ready = "QWERTYUIOPASDFGHJKZXCVBNMqwertyuiopasdfghjkzxcvbnm1234567890";

        //生成随机脚标
        Random ran = new Random();
        g.setColor(Color.blue);

        StringBuilder sb = new StringBuilder();
        for(int i = 0;i < 4;++i)
        {
    
    
            int index = ran.nextInt(ready.length());
            char ch = ready.charAt(index);

            sb.append(ch);
            g.drawString(ch+"",width / 5 *i,height/2);
        }
        HttpSession session = request.getSession(); //把这次生成的验证码存入session中,供登入请求比对
        session.setAttribute("checkcode",sb.toString());

        //2.4 划干扰线
        int TheNumeberOfLine = 10;
        g.setColor(Color.green);
        for(int i = 0;i < TheNumeberOfLine;i++)
        {
    
    
            int x1 = ran.nextInt(width);
            int x2 = ran.nextInt(width);
            int y1 = ran.nextInt(height);
            int y2 = ran.nextInt(height);

            g.drawLine(x1,y1,x2,y2);
        }

        //3.将图片输出到页面上  参数:待输出图片,格式,输出位置
        ImageIO.write(image,"jpg",response.getOutputStream());

    }

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

success.jsp 成功跳转页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>SuccessLogin</title>
</head>
<body>
        <h1> <%=request.getSession().getAttribute("user")%></h1>
</body>
</html>

LoginServlet --登入页面的核心逻辑
要注意以下几点:
1.一般来说都是先判断验证码再判断密码对不对。因为验证码是生成的,不和数据库相连,所以没有数据库开销。
2.转发和重定向的区别。主要是数据位于的域的不同,还有请求次数的不同。
3.经过测试发现,本案例中的两个跳转转发可以转成重定向,但逆向是不可以的。

4.想输出某段文本,可以把这段话起一个总结性的英文key值,这样就可以在jsp前端中很好的体现了。

package cn.web.Servlet;

import cn.web.Dao.UserDao;
import cn.web.Domain.User;

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;

@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
    
    
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        //1.设置编码
        request.setCharacterEncoding("utf-8");
        //2.获取参数
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String checkcode = request.getParameter("checkcode");

        //封装一下username和Password信息为loginUser
        User loginUser = new User();
        loginUser.setName(username);
        loginUser.setPassword(password);

        //3.获取生成的验证码 由于图片是一次请求,输入验证码后登入是另一次
        // 所以用重定向来实现,即在session中拿数据
        HttpSession session = request.getSession();
        String checkcode_session = (String) session.getAttribute("checkcode");

        //4.先判断验证码是否正确
        if (checkcode_session.equalsIgnoreCase(checkcode))
        {
    
    
            //忽略大小写比较字符串
            //验证码正确
            //判断用户名和密码是否一致
            UserDao dao = new UserDao();
            User user = dao.Login(loginUser);

            if(user == null) //没在数据库中找到,查找失败
            {
    
    
                //存储信息
                request.setAttribute("up_error","用户名或密码错误");
                //转发到登入页面
                request.getRequestDispatcher("/Login.jsp").forward(request,response);
//                session.setAttribute("up_error","用户名或密码错误");
//                response.sendRedirect(request.getContextPath() + "/Login.jsp");

            }
            else {
    
    //登入成功
                //存储成功的信息
                session.setAttribute("user",user); //user对象传输到session域

                //重定向  (???为啥这里是重定向,上面却是转发???)(经测试,全是重定向也可以完成功能)
                //绝对路径
                response.sendRedirect(request.getContextPath() + "/success.jsp");
            }
        }
        else
        {
    
    
            //验证码不一致
            //存储信息到request域中供转发使用 (要输出是啥错了)
            request.setAttribute("cc_error","验证码错误");
            //转发到登入页面
            request.getRequestDispatcher("/Login.jsp").forward(request,response);

        }
    }

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

剩下的部分基本上和之前那个登入案例十分类似,这里逻辑就不在赘述了。

JDBCUtils工具类

package cn.web.utils;

import com.alibaba.druid.pool.DruidDataSourceFactory;
import com.sun.xml.internal.ws.policy.privateutil.PolicyUtils;

import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

/**
 * JDBC工具类,使用Durid连接池
 */
public class JDBCUtils {
    
    

    private static DataSource ds;

    static {
    
    
        try {
    
    
            //1.加载配置文件
            Properties pro = new Properties();
            //使用ClassLoader加载配置文件获取字节输入流
            InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");

            pro.load(is);
            //2.初始化连接池对象 一开始报错了,因为lib没有加入到工作空间
            //解决方法:右键lib->Add as Library ->module library

            ds = DruidDataSourceFactory.createDataSource(pro);
        }
        catch (IOException e){
    
    
            e.printStackTrace();
        }
        catch (Exception e) {
    
    
            e.printStackTrace();
        }
    }
    /**
     * 获取连接池对象
     */
    public static DataSource getDateSource(){
    
    
        return ds;
    }
    /**
     * 获取连接connection对象
     */
    public static Connection getConnection() throws SQLException{
    
    
        return ds.getConnection();
    }
}

Dao类(数据访问对象)

package cn.web.Dao;

import cn.web.Domain.User;
import cn.web.utils.JDBCUtils;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;

public class UserDao {
    
    

    //声明JDBCTemplate 对象公用
    private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDateSource());

    public User Login(User loginUser)
    {
    
    

        try {
    
    
            String sql = "select * from user where username = ? AND password = ?";

            //把loginUser输入的名字和密码写成spq去数据库里面找
            User user = template.queryForObject(sql,new BeanPropertyRowMapper<>(User.class),
                    loginUser.getName(),loginUser.getPassword());

            return user;
        } catch (DataAccessException e) {
    
    
            e.printStackTrace();
            return null; //如果没找到返回一个控制住
        }
    }
}

自定义用户类

package cn.web.Domain;

public class User {
    
    
    private int id;
    private String username;
    private String password;

    public int getId() {
    
    
        return id;
    }

    public void setId(int id) {
    
    
        this.id = id;
    }

    public String getName() {
    
    
        return username;
    }

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

    public String getPassword() {
    
    
        return password;
    }

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

    @Override
    public String toString()
    {
    
    
        return "User{" +
            "id=" + id +
            ", username='" + username + '\'' +
            ", password='" + password + '\'' +
            '}';
    }
}

猜你喜欢

转载自blog.csdn.net/abyss_miracle/article/details/113733683