网站自动登录操作分析,我以CSDN用户登录功能为例说明,
1.进入csdn网站的登录界面 地址: CSDN用户登录界面 界面效果如下:
2.输入正确的用户名和密码,并且勾选上 下次自动登录功能
3.点击登录,如果成功登录,就会跳转到登陆成功的界面.
4.如果你再去点击CSDN用户登录界面 看看什么效果,你会发现,打不开此登录界面,直接跳转到了如下图界面:
5.可以看到此时,已经完成了自动登录的功能模块.
根据以上分析,我结合Java Web中的Filter和Cookie完成一个网站自动登录的功能模块.
1.编写登录界面
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP 'index.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> ${requestScope.msg}<br/> <form action="${pageContext.request.contextPath}/AdminOper.do" method="post"> <table> <tr> <td>用户名:</td> <td><input type="text" name="name"/></td> </tr> <tr> <td>密码:</td> <td><input type="password" name="pass"/></td> </tr> <tr> <td colspan="2"> <input type="radio" name="day" checked="checked" value="7">一周 <input type="radio" name="day" value="30">一月 <input type="radio" name="day" value="90">三个月 </td> </tr> <tr> <td><input type="checkbox" name="mark" value="mark"/></td> <td>下次自动登陆</td> </tr> <tr> <td> <input type="submit" value="登陆"/></td> <td><input type="reset" value="重置"/></td> </tr> </table> <input type="hidden" name="oper" value="login"/> </form> </body> </html>
效果如下:
2.登录界面处理的servlet类.
package www.csdn.net.day56.servlet; import java.io.IOException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import sun.misc.BASE64Encoder; import com.sun.mail.util.BASE64EncoderStream; import www.csdn.net.day56.bean.Admin; import www.csdn.net.day56.dao.AdminDao; import www.csdn.net.day56.dao.impl.AdminDaoImpl; import www.csdn.net.day56.service.AdminService; import www.csdn.net.day56.service.impl.AdminServiceImpl; public class AdminServlet extends HttpServlet { private AdminService adminService = new AdminServiceImpl(); private long expires = 24 * 60 * 60; // 1天 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String method = request.getMethod(); System.out.println("请求的方法::::" + method); // 获取请求参数中 操作的标识符 String oper = request.getParameter("oper"); if ("login".equals(oper)) { // 处理登陆 // 获取用户名和密码 String name = request.getParameter("name"); String pass = request.getParameter("pass"); //获取标记 是否自动登录标识符 String mark = request.getParameter("mark"); // 验证用户名和密码是否正确 Admin entity = adminService.checkLogin(name, pass); if (entity != null) { // 判断是自动登录处理 if ("mark".equals(mark)) { // 获取默认记住的天数 String day = request.getParameter("day"); // 转换成有效的时间 expires = Integer.valueOf(day) * expires; // 声明cookie Cookie autoCookie = null; // 获取所有cookie Cookie cookies[] = request.getCookies(); // 遍历cookie for (Cookie cookie : cookies) { // 判断是否存在自动登陆记录 if ("autologin".equals(cookie.getName())) { autoCookie = cookie; // 赋值 // 当cookie存在的时候,我需要重新设置值 long time = (System.currentTimeMillis() + expires * 1000); //cookie拼接的value值,(可以根据自己的想法设计) String newValue = name + ":" + time + ":" + md5Value(name + ":" + pass + ":" + time); //设置值 autoCookie .setValue(newValue); } else { // 不存在创建 // name+":"+time+":"+md5(name:pass:time) long time = System.currentTimeMillis() + expires * 1000; //cookie拼接的value值,(可以根据自己的想法设计) String cookieValue = name + ":" + time + ":" + md5Value(name + ":" + pass + ":" + time); //创建cookie autoCookie = new Cookie("autologin", cookieValue); } } autoCookie.setMaxAge((int) expires); autoCookie.setPath("/day56"); // 添加cookie response.addCookie(autoCookie); } // admin存入到session request.getSession().setAttribute("admin", entity); // 成功登陆后的操作 request.getRequestDispatcher("./sc.jsp").forward(request, response); } else { request.setAttribute("msg", "用户名或者密码错误"); request.getRequestDispatcher("./index.jsp").forward(request, response); } } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } /** * md5加密处理 * @param value * @return */ public String md5Value(String value) { try { MessageDigest digest = MessageDigest.getInstance("md5"); byte result[] = digest.digest(value.getBytes()); BASE64Encoder encoder = new BASE64Encoder(); return encoder.encode(result); } catch (NoSuchAlgorithmException e) { // TODO Auto-generated catch block e.printStackTrace(); } return ""; } }
3.有关自动完成登录过滤器的代码如下
package www.csdn.net.day56.filter; import java.io.IOException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import sun.misc.BASE64Encoder; import www.csdn.net.day56.bean.Admin; import www.csdn.net.day56.service.AdminService; import www.csdn.net.day56.service.impl.AdminServiceImpl; public class AutoLoginFilter implements Filter { @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { // 造型对象 HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; // 1.首先判断sesion中有没有admin Object object = request.getSession().getAttribute("admin"); // 如果session中有用户 if (object != null) { // 跳转到成功登录的界面 request.getRequestDispatcher("./sc.jsp").forward(request, response); return; } /*---------------------------以下是当session中不存在admin信息时候的处理---------------------------------*/ // 2.判断cookie中是否存在 autologin标识符 的cookie对象 // 声明cookie Cookie autoCookie = null; // 获取所有的cookie Cookie cookies[] = request.getCookies(); // 如果没有cookie信息,就继续执行login.do,跳转到login.jsp页面 if (cookies != null) { // 如果有,就遍历cookie for (Cookie cookie : cookies) { // 判断cookie中是否有autologin标识符的cookie if ("autologin".equals(cookie.getName())) { autoCookie = cookie; // 如果有 就赋值给临时变量autoCookie } } // 3. 判断autoCookie是否等于null if (autoCookie == null) { // 如果等于null,则继续执行login.jsp页面 chain.doFilter(request, response); return; } // 3.如果autoCookie不等于null,就判断cookie的值 // 获取cookie值 String value = autoCookie.getValue(); // 拆分cookie的值 String temp[] = value.split(":"); System.out.println(temp.length); // 判断长度 是否等于自己拼接的长度 if (temp.length != 3) { // 如果不等于3,则继续执行login.jsp页面 chain.doFilter(request, response); return; } // 获取cookie拆分的各个值 String name = temp[0]; // 用户名 String time = temp[1];// 获取有效时间 String service_md5Value = temp[2];// 获取md5的加密后的字符 // 4.判断cookie是否失效 if (Long.valueOf(time) <= System.currentTimeMillis()) { // 如果失效,则继续执行login.jsp页面 chain.doFilter(request, response); return; } // 5.如果cookie没有失效,根据用户名,去查询用户信息 AdminService adminService = new AdminServiceImpl(); // 查询用户信息 Admin entity = adminService.checkLogin(name); System.out.println(entity+"0000"); // 判断用户是否为null if (entity == null) { // 如果没有查询的用户,则继续执行login.jsp页面 chain.doFilter(request, response); return; } // 按照服务器拼接的字符的方式,拼接md5加密的字符串 String md5Temp = entity.getName() + ":" + entity.getPass() + ":" + time; // 判断md5加密后和服务器端加密的字符是否相等 if (!(md5Value(md5Temp).equals(service_md5Value))) { // 在不相等的情况下,则继续执行login.jsp页面 chain.doFilter(request, response); return; } // 如果满足了cookie取值判断的所有结果,则跳转到成功登录的界面. request.getSession().setAttribute("admin", entity); request.getRequestDispatcher("./sc.jsp").forward(request, response); } else { // 在没有cookie信息的时候,则继续login.jsp页面 chain.doFilter(request, response); return; } } // md5加密字符串 public String md5Value(String value) { try { MessageDigest digest = MessageDigest.getInstance("md5"); byte result[] = digest.digest(value.getBytes()); BASE64Encoder encoder = new BASE64Encoder(); return encoder.encode(result); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return ""; } @Override public void init(FilterConfig arg0) throws ServletException { // TODO Auto-generated method stub } @Override public void destroy() { // TODO Auto-generated method stub } }
4.在web.xml文件中配置过滤器
<filter> <filter-name>AutoLoginFilter</filter-name> <filter-class>www.csdn.net.day56.filter.AutoLoginFilter</filter-class> </filter> <filter-mapping> <filter-name>AutoLoginFilter</filter-name> <url-pattern>/login.jsp</url-pattern> </filter-mapping>
5.以上功能模块中涉及到的类或者接口如下:
1.Admin.java类
package www.csdn.net.day56.bean; import java.io.Serializable; public class Admin implements Serializable{ /** * */ private static final long serialVersionUID = 1L; private Integer id; private String name; private String pass; public Admin() { super(); // TODO Auto-generated constructor stub } public Admin(Integer id, String name, String pass) { super(); this.id = id; this.name = name; this.pass = pass; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPass() { return pass; } public void setPass(String pass) { this.pass = pass; } }
2.BaseDao接口
package www.csdn.net.day56.dao; public interface BaseDao<T, PK> { }
3.AdminDao接口
package www.csdn.net.day56.dao; import www.csdn.net.day56.bean.Admin; public interface AdminDao extends BaseDao<Admin,Integer>{ /** * 用户登录验证的操作 * @param name * @param pass * @return */ public Admin checkLogin(String name,String pass); /** * * @param name * @return */ public Admin checkLogin(String name); }
4.AdminDao接口的实现类
package www.csdn.net.day56.dao.impl; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import util.DBConn; import www.csdn.net.day56.bean.Admin; import www.csdn.net.day56.dao.AdminDao; public class AdminDaoImpl implements AdminDao { private Connection conn; private PreparedStatement pstmt; private ResultSet rs; @Override public Admin checkLogin(String name, String pass) { Admin entity = null; conn = DBConn.getConn(); String sql = "select * from admin where name=? and pass=? "; try { pstmt = conn.prepareStatement(sql); int index = 1; pstmt.setString(index++, name); pstmt.setString(index++, pass); rs = pstmt.executeQuery(); if (rs.next()) { entity = new Admin(); entity.setId(rs.getInt("id")); entity.setName(rs.getString("name")); entity.setPass(rs.getString("pass")); } } catch (Exception e) { } finally { DBConn.release(rs, pstmt); } return entity; } @Override public Admin checkLogin(String name) { Admin entity = null; conn = DBConn.getConn(); String sql = "select * from admin where name=? "; try { pstmt = conn.prepareStatement(sql); int index = 1; pstmt.setString(index++, name); rs = pstmt.executeQuery(); if (rs.next()) { entity = new Admin(); entity.setId(rs.getInt("id")); entity.setName(rs.getString("name")); entity.setPass(rs.getString("pass")); } } catch (Exception e) { } finally { DBConn.release(rs, pstmt); } return entity; } }
5.BaseService接口
package www.csdn.net.day56.service; public interface BaseService<T, PK> { }
6.AdminService接口
package www.csdn.net.day56.service; import www.csdn.net.day56.bean.Admin; public interface AdminService extends BaseService<Admin, Integer> { /** * 用户登录验证的操作 * @param name * @param pass * @return */ public Admin checkLogin(String name,String pass); /** * * @param name * @return */ public Admin checkLogin(String name); }
7.AdminService接口的实现类
package www.csdn.net.day56.service.impl; import www.csdn.net.day56.bean.Admin; import www.csdn.net.day56.dao.AdminDao; import www.csdn.net.day56.dao.impl.AdminDaoImpl; import www.csdn.net.day56.service.AdminService; public class AdminServiceImpl implements AdminService { private AdminDao adminDao = new AdminDaoImpl(); @Override public Admin checkLogin(String name, String pass) { Admin entity = adminDao.checkLogin(name, pass); return entity; } @Override public Admin checkLogin(String name) { return adminDao.checkLogin(name); } }
8.工具类
package util; import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Properties; import org.apache.commons.io.FileUtils; public class DBConn { private static Connection conn; private DBConn() { } public static Connection getConn() { try { if (conn == null) { // 创建集合对象 Properties properties = new Properties(); // 装载 properties.load(DBConn.class.getClassLoader() .getResourceAsStream("db.properties")); // 加载驱动程序 Class.forName(properties.getProperty("driverClassName")); // 获取连接对象 conn = DriverManager.getConnection( properties.getProperty("url"), properties.getProperty("user"), properties.getProperty("pass")); // 修改事务 为手动提交方式 conn.setAutoCommit(false); } } catch (Exception e) { e.printStackTrace(); } return conn; } public static void update(String sql, Object params[], PreparedStatement pstmt) throws Exception { try { pstmt = getConn().prepareStatement(sql); for (int i = 0; i < params.length; i++) { pstmt.setObject(i + 1, params[i]); } pstmt.executeUpdate(); conn.commit(); } catch (Exception e) { conn.rollback(); e.printStackTrace(); } finally { release(null, pstmt); } } public static void release(ResultSet rs, PreparedStatement pstmt) { if (rs != null) { try { rs.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if (pstmt != null) { try { pstmt.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
下面进行效果演示说明
1.打开登录界面,输入正确的用户名和密码,勾选上自动登录操作.
2.点击登录按钮,登录成功后,跳转到sc.jsp页面
3.重新进入登录界面
发现,完成了自动登录的功能模块.
如果你关闭tomcat,重新启动,你会发现,只要在cookie的有效时间中,并且用户名和密码没有做修改的情况下,只要你进入登录界面.用户就会自动登录,并跳转到sc.jsp页面.效果同上图.