網站自動登入操作分析,我以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;// 聲明cookieCookie autoCookie = null;// 擷取所有cookieCookie cookies[] = request.getCookies();// 遍曆cookiefor (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);//建立cookieautoCookie = new Cookie("autologin", cookieValue);}}autoCookie.setMaxAge((int) expires);autoCookie.setPath("/day56");// 添加cookieresponse.addCookie(autoCookie);}// admin存入到sessionrequest.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 blocke.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 {@Overridepublic void doFilter(ServletRequest req, ServletResponse res,FilterChain chain) throws IOException, ServletException {// 造型對象HttpServletRequest request = (HttpServletRequest) req;HttpServletResponse response = (HttpServletResponse) res;// 1.首先判斷sesion中有沒有adminObject object = request.getSession().getAttribute("admin");// 如果session中有使用者if (object != null) {// 跳轉到成功登入的介面request.getRequestDispatcher("./sc.jsp").forward(request, response);return;}/*---------------------------以下是當session中不存在admin資訊時候的處理---------------------------------*/// 2.判斷cookie中是否存在 autologin標識符 的cookie對象// 聲明cookieCookie autoCookie = null;// 擷取所有的cookieCookie cookies[] = request.getCookies();// 如果沒有cookie資訊,就繼續執行login.do,跳轉到login.jsp頁面if (cookies != null) {// 如果有,就遍曆cookiefor (Cookie cookie : cookies) {// 判斷cookie中是否有autologin標識符的cookieif ("autologin".equals(cookie.getName())) {autoCookie = cookie; // 如果有 就賦值給臨時變數autoCookie}}// 3. 判斷autoCookie是否等於nullif (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");// 判斷使用者是否為nullif (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 "";}@Overridepublic void init(FilterConfig arg0) throws ServletException {// TODO Auto-generated method stub}@Overridepublic 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;@Overridepublic 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;}@Overridepublic 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();@Overridepublic Admin checkLogin(String name, String pass) {Admin entity = adminDao.checkLogin(name, pass);return entity;}@Overridepublic 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 blocke.printStackTrace();}}if (pstmt != null) {try {pstmt.close();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}
下面進行效果示範說明
1.開啟登入介面,輸入正確的使用者名稱和密碼,勾選上自動登入操作.
2.點擊登入按鈕,登入成功後,跳轉到sc.jsp頁面
3.重新進入登入介面
發現,完成了自動登入的功能模組.
如果你關閉tomcat,重新啟動,你會發現,只要在cookie的有效時間中,並且使用者名稱和密碼沒有做修改的情況下,只要你進入登入介面.使用者就會自動登入,並跳轉到sc.jsp頁面.效果同.