Dict.CN 在線詞典, 英語學習, 在線翻譯

          都市淘沙者

          荔枝FM Everyone can be host

          統計

          留言簿(23)

          積分與排名

          優秀學習網站

          友情連接

          閱讀排行榜

          評論排行榜

          安全的實現兩星期內自動登陸功能(轉)

           現在很多網站都有為用戶保存登陸信息(即保存Cookie)的功能,當用戶下一次進入網站時,可以幫助用戶自動登陸,使網站顯得更加友好。筆者通過研究ACEGI項目的自動登陸源碼,編寫了一個安全有效的實現兩星期自動登陸功能的JAVA工具類,在此要感謝傳智播客公司教學總監張孝祥老師向筆者推薦了ACEGI項目。下面是具體的實現流程和實現代碼。

          先說一下流程:

          1.  保存用戶信息階段:

          當用戶登陸網站時,在登陸頁面填寫完用戶名和密碼后,如果用戶在提交時還選擇了“兩星期內自動登陸”復選框,那么在后臺程序中驗證用戶名和密碼全都正確后,還要為用戶保存這些信息,以便用戶下一次可以直接進入網站;如果用戶沒有勾選“兩星期內自動登陸”復選框,則不必為用戶保存信息,那么用戶在下一次登陸網站時仍需要填寫用戶名和密碼。

               在保存用戶信息階段,主要的工作是對用戶的信息進行加密并保存到客戶端。加密用戶的信息是較為繁瑣的,大致上可分 為以下幾個步聚:

          得到用戶名、經MD5加密后的用戶密碼、cookie有效時間(本文設置的是兩星期,可根據自己需要修改)

          自定義的一個webKey,這個Key是我們為自己的網站定義的一個字符串常量,這個可根據自己需要隨意設置

          將上兩步得到的四個值得新連接成一個新的字符串,再進行MD5加密,這樣就得到了一個MD5明文字符串

          將用戶名、cookie有效時間、MD5明文字符串使用“:”間隔連接起來,再對這個連接后的新字符串進行Base64編碼

          設置一個cookieName,cookieName和上一步產生的Base64編碼寫入到客戶端。

                       

          2.  讀取用戶信息:

          其實弄明白了保存原理,讀取及校驗原理就很容易做了。讀取和檢驗可以分為下面幾個步驟:

          根據設置的cookieName,得到cookieValue,如果值為空,就不幫用戶進行自動登陸;否則執行讀取方法

          cookieValue進行Base64解碼,將取得的字符串以split(“:”)進行拆分,得到一個String數組cookieValues(此操作與保存階段的第4步正好相反),這一步將得到三個值:

                 cookieValues[0] ---- 用戶名

                 cookieValues[1] ---- cookie有效時間

                 cookieValues[2] ---- MD5明文字符串

          判斷cookieValues的長度是否為3,如果不為3則進行錯誤處理。

          如果長度等于3,取出第二個,cookieValues[1],此時將會得到有效時間(long型),將有效時間與服務器系統當前時間比較,如果小于當前時間,則說明cookie過期,進行錯誤處理。

          如果cookie沒有過期,就取cookieValues[0],這樣就可以得到用戶名了,然后去數據庫按用戶名查找用戶。

          如果上一步返回為空,進行錯誤處理。如果不為空,那么將會得到一個已經封裝好用戶信息的User實例對象user

          取出實例對象user的用戶名、密碼、cookie有效時間(即cookieValues[1])、webKey,然后將四個值連接起來,然后進行MD5加密,這樣做也會得到一個MD5明文字符串(此操作與保存階段的第3步類似)

          將上一步得到MD5明文與cookieValues[2]進行equals比較,如果是false,進行錯誤處理;如果是true,則將user對象添加到session中,幫助用戶完成自動登陸

          完整的代碼,用途請參見注釋

          CookieUtil.java

          處理cookie的工具類,包括讀取,保存,清除三個主要方法。

          package cn.itcast.util;


          import java.io.IOException;

          import java.io.PrintWriter;

          import java.io.UnsupportedEncodingException;


          import javax.servlet.FilterChain;

          import javax.servlet.ServletException;

          import javax.servlet.http.Cookie;

          import javax.servlet.http.HttpServletRequest;

          import javax.servlet.http.HttpServletResponse;

          import javax.servlet.http.HttpSession;

          import java.security.MessageDigest;

          import java.security.NoSuchAlgorithmException;


          import cn.itcast.bean.User;

          import cn.itcast.dao.UserDAO;

          import cn.itcast.factory.DaoImplFactory;

          import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;


          /*

           * 2007.09.21 by lyhapple

           * 
          */



          public class CookieUtil {

                 
          //保存cookie時的cookieName

                 
          private final static String cookieDomainName = “cn.itcast”;

                 

                 
          //加密cookie時的網站自定碼

                 
          private final static String webKey = “itcast”;

                 

          //設置cookie有效期是兩個星期,根據需要自定義

                 
          private final static long cookieMaxAge = 60 * 60 * 24 * 7 * 2;

                 

                 
          //保存Cookie到客戶端--------------------------------------------------------------------------------------------------------

                 
          //在CheckLogonServlet.java中被調用

                 
          //傳遞進來的user對象中封裝了在登陸時填寫的用戶名與密碼

                 
          public static void saveCookie(User user, HttpServletResponse response) {

                        

                        
          //cookie的有效期

                        
          long validTime = System.currentTimeMillis() + (cookieMaxAge * 1000);

                        

                        
          //MD5加密用戶詳細信息

                        String cookieValueWithMd5 
          =getMD5(user.getUserName() + ":" + user.getPassword()

                                      
          + ":" + validTime + ":" + webKey);

                        

                        
          //將要被保存的完整的Cookie值

                        String cookieValue 
          = user.getUserName() + ":" + validTime + ":" + cookieValueWithMd5;

                        

                        
          //再一次對Cookie的值進行BASE64編碼

                        String cookieValueBase64 
          = new String(Base64.encode(cookieValue.getBytes()));

                        

                        
          //開始保存Cookie

                        Cookie cookie 
          = new Cookie(cookieDomainName, cookieValueBase64);

                        
          //存兩年(這個值應該大于或等于validTime)

          cookie.setMaxAge(
          60 * 60 * 24 * 365 * 2); 

          //cookie有效路徑是網站根目錄

                        cookie.setPath(
          "/");

                        
          //向客戶端寫入

                        response.addCookie(cookie);

                 }


                 

                 
          //讀取Cookie,自動完成登陸操作--------------------------------------------------------------------------------------------

                 
          //在Filter程序中調用該方法,見AutoLogonFilter.java

                 
          public static void readCookieAndLogon(HttpServletRequest request, HttpServletResponse response, 

          FilterChain chain) 
          throws IOException, ServletException,UnsupportedEncodingException{

                               

          //根據cookieName取cookieValue

          Cookie cookies[] 
          = request.getCookies();

                               String cookieValue 
          = null;

                               
          if(cookies!=null){

                                      
          for(int i=0;i<cookies.length;i++){

                                             
          if (cookieDomainName.equals(cookies[i].getName())) {

                                                    cookieValue 
          = cookies[i].getValue();

                                                    
          break;

                                             }


                                      }


                               }



                               
          //如果cookieValue為空,返回,

                               
          if(cookieValue==null){

                                      
          return;

                               }


                        

                        
          //如果cookieValue不為空,才執行下面的代碼

                        
          //先得到的CookieValue進行Base64解碼

                        String cookieValueAfterDecode 
          = new String (Base64.decode(cookieValue),"utf-8"); 

                        

                        
          //對解碼后的值進行分拆,得到一個數組,如果數組長度不為3,就是非法登陸

                        String cookieValues[] 
          = cookieValueAfterDecode.split(":");

                        
          if(cookieValues.length!=3){

                               response.setContentType(
          "text/html;charset=utf-8");

                               PrintWriter out 
          = response.getWriter();

                               out.println(
          "你正在用非正常方式進入本站");

                               out.close();

                               
          return;

                        }


                        

                        
          //判斷是否在有效期內,過期就刪除Cookie

                        
          long validTimeInCookie = new Long(cookieValues[1]);

                        
          if(validTimeInCookie < System.currentTimeMillis()){

                               
          //刪除Cookie

                               clearCookie(response);

                               response.setContentType(
          "text/html;charset=utf-8");

                               PrintWriter out 
          = response.getWriter();

                               out.println(
          "<a href=’logon.jsp’>你的Cookie已經失效,請重新登陸</a>");

                               out.close();

                               
          return;

                        }


                        

                        
          //取出cookie中的用戶名,并到數據庫中檢查這個用戶名,

                        String username 
          = cookieValues[0];

                        

                        
          //根據用戶名到數據庫中檢查用戶是否存在

                        UserDAO ud 
          = DaoImplFactory.getInstance();

                        User user 
          = ud.selectUserByUsername(username);

                        

                        
          //如果user返回不為空,就取出密碼,使用用戶名+密碼+有效時間+ webSiteKey進行MD5加密

                        
          if(user!=null){

                               String md5ValueInCookie 
          = cookieValues[2];

                               String md5ValueFromUser 
          =getMD5(user.getUserName() + ":" + user.getPassword()

                                             
          + ":" + validTimeInCookie + ":" + webKey);

                               
          //將結果與Cookie中的MD 5碼 相比較,如果相同,寫入Session,自動登陸成功,并繼續用戶請求

                               
          if(md5ValueFromUser.equals(md5ValueInCookie)){

                                      HttpSession session 
          = request.getSession(true);

                                      session.setAttribute(
          "user", user);

                                      chain.doFilter(request, response);

                               }


                        }
          else{

                 
          //返回為空執行

                               response.setContentType(
          "text/html;charset=utf-8");

                               PrintWriter out 
          = response.getWriter();

                               out.println(
          "cookie驗證錯誤!");

                               out.close();

                 
          return;

          }


                 }


                 

                 
          //用戶注銷時,清除Cookie,在需要時可隨時調用------------------------------------------------------------

                 
          public static void clearCookie( HttpServletResponse response){

                        Cookie cookie 
          = new Cookie(cookieDomainName, null);

                        cookie.setMaxAge(
          0);

                        cookie.setPath(
          "/");

                        response.addCookie(cookie);

                 }



          //獲取Cookie組合字符串的MD 5碼 的字符串----------------------------------------------------------------------------

                        
          public static String getMD5(String value) {

                               String result 
          = null;

                               
          try{

                                      
          byte[] valueByte = value.getBytes();

                                      MessageDigest md 
          = MessageDigest.getInstance("MD5");

                                      md.update(valueByte);

                                      result 
          = toHex(md.digest());

                               }
           catch (NoSuchAlgorithmException e2){

                                      e1.printStackTrace();

          }


                               
          return result;

                        }


                 

          //將傳遞進來的字節數組轉換成十六進制的字符串形式并返回

                        
          private static String toHex(byte[] buffer){

                               StringBuffer sb 
          = new StringBuffer(buffer.length * 2);

                               
          for (int i = 0; i < buffer.length; i++){

                                      sb.append(Character.forDigit((buffer[i] 
          & 0xf0>> 416));

                                      sb.append(Character.forDigit(buffer[i] 
          & 0x 0f , 16));

                               }


                               
          return sb.toString();

                        }


          }

          下面的是對CookieUtil工具類各方法的調用演示:

          User.java

          封裝用戶信息的JavaBean對象模型

          package com.itcast.bean;


          public class User {

                 
          private int id;

                 

                 
          private String userName;


                 
          private String password;

                 

                 
          public String getPassword() {

                        
          return password;

                 }



                 
          public void setPassword(String password) {

                        
          this.password = password;

                 }



                 
          public String getUserName() {

                        
          return userName;

                 }



                 
          public void setUserName(String userName) {

                        
          this.userName = userName;

                 }



                 
          public int getId() {

                        
          return id;

                 }



                 
          public void setId(int id) {

                        
          this.id = id;

                 }


          }


          AutoLogonFilter.java

          過濾器程序,可在WEB-INF/web.xml中設置過濾規則,本文對過濾規則不作介紹,此程序主要作用是檢查用戶在上一次登陸時是否保存了Cookie,如果保存了,就處理Cookie信息,并幫助用戶自動登陸

          本程序主要調用了CookieUtil.java中的讀取與自動登陸方法,即readCookieAndLogon方法

          package cn.itcast.filter;


          import java.io.IOException;


          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 javax.servlet.http.HttpSession;


          import cn.itcast bean.User;

          import cn.itcast.util.CookieUtil;


          public class AutoLogonFilter implements Filter {

                 

                 
          public void destroy() {

                 }


                 

          //保存cookie時的cookieName,與CookieUtil.java中的設置相同 

                 
          private final static String cookieDomainName = “cn.itcast”;

                 

                 
          public void doFilter(ServletRequest req, ServletResponse resp,

                               FilterChain chain) 
          throws IOException, ServletException {

                        HttpServletRequest request 
          = (HttpServletRequest)req;

                        HttpServletResponse response 
          = (HttpServletResponse)resp;

                        HttpSession session 
          = request.getSession(true);

                        User user 
          = (User)session.getAttribute("user");

                        

                        
          //如果封裝的user不為空,說明已經登陸,則繼續執行用戶的請求.下面的就不處理了

                        
          if(user!=null){

                               chain.doFilter(request,response);

                               
          return;

                        }


                        

                        
          //user為空,說明用戶還沒有登陸,就嘗試得到瀏覽器傳送過來的Cookie

                        Cookie cookies[] 
          = request.getCookies();

                        String cookieValue 
          = null;

                        
          if(cookies!=null){

                               
          for(int i=0;i<cookies.length;i++){

                                      
          if (cookieDomainName.equals(cookies[i].getName())) {

                                             cookieValue 
          = cookies[i].getValue();

                                             
          break;

                                      }


                               }


                        }



                        
          //如果cookieValue為空,也繼續執行用戶請求

                        
          if(cookieValue==null){

                               chain.doFilter(request,response);

                               
          return;

                        }



                        
          //cookieValue不為空執行下面的方法,調用CookieUtil.java中的readCookieAndLogon方法 

                        
          try{

                               CookieUtil.readCookieAndLogon(cookieValue, request, response, chain);

                        }
          catch(Exception e){

                               e.printStackTrace();

                        }


                 }



                 
          public void init(FilterConfig arg0) throws ServletException {

                 }


          }


          CheckLogonServlet.java

          驗證用戶登陸信息的Servlet,此程序調用了CookieUtil.java中的saveCookie方法

          package cn.itcast.servlet;


          /*

           * update 2007.09.23 by lyhapple

           * 檢查用戶登陸

           * 
          */



          import java.io.IOException;


          import javax.servlet.ServletException;

          import javax.servlet.http.HttpServlet;

          import javax.servlet.http.HttpServletRequest;

          import javax.servlet.http.HttpServletResponse;

          import javax.servlet.http.HttpSession;


          import cn.itcast.bean.User;

          import cn.itcast.dao.UserDAO;

          import cn.itcast.factory.DaoImplFactory;

          import cn.itcast.util.CookieUtil;


          public class CheckLogonServlet extends HttpServlet {


                 
          public void doGet(HttpServletRequest request, HttpServletResponse response)

                               
          throws ServletException, IOException {

                        doPost(request, response);

                 }



                 
          public void doPost(HttpServletRequest request, HttpServletResponse response)

                               
          throws ServletException, IOException {

                        request.setCharacterEncoding(
          "utf-8");

                        String username 
          = request.getParameter("username").trim();

                        String password 
          = CookieUtil.getMD5(request.getParameter("password"));

                        String remeberMe 
          = request.getParameter("remeberMe");

                        HttpSession session 
          = request.getSession(false);


                        
          // 將接收到的用戶名傳遞到UserDao的checkUser方法中,檢查用戶

                        
          // 返回一個User類型的對象

                        UserDAO ud 
          = DaoImplFactory.getInstance();

                        User user 
          = ud.selectUserByUsername(username);

                        
          if (user == null{

                               request.setAttribute(
          "checkUserError","<a href='register.jsp'><font color=red>用戶名不存在,請先注冊</font></a>");

                               request.getRequestDispatcher(
          "index.jsp").forward(request, response);

                               
          return;

                        }



                        
          if(!password.equals(user.getPassword())){

                               request.setAttribute(
          "checkPasswordError","<font color=red>密碼輸入錯誤,請重新輸入</font>");

                               request.getRequestDispatcher(
          "index.jsp").forward(request, response);

                               
          return;

                        }


                        

                        
          //保存Cookie,這里調用了CookieUtil.java中的saveCookie方法,將上面的user對象作為參數傳遞 

                        
          if ("on".equals(remeberMe)) {

                               CookieUtil.saveCookie(user, response);

                        }


                        
          //在Session中保存用戶信息,并轉向用戶的個人信息頁面

                        session.setAttribute(
          "user", user);

                        request.getRequestDispatcher(
          "User/userInfo.jsp").forward(request,response);

                 }


          }

          UserDAO.javaDaoImplFactory.java屬于持久層相關的程序,這里就不貼出來了,讀者可根據自己需要選擇不同的持久層框架,在本程序中只要實現查詢用戶的功能就可以了

          posted on 2007-10-11 12:39 都市淘沙者 閱讀(448) 評論(0)  編輯  收藏 所屬分類: Java Basic/Lucene/開源資料

          主站蜘蛛池模板: 武宁县| 昆明市| 达州市| 米泉市| 涞水县| 虹口区| 舟曲县| 揭东县| 沁水县| 东明县| 永仁县| 哈尔滨市| 高密市| 赣榆县| 镇赉县| 闽清县| 榆林市| 浦东新区| 鹿邑县| 渝北区| 麻江县| 华宁县| 南丹县| 九江县| 杭锦后旗| 卓资县| 高碑店市| 临高县| 庆安县| 尼玛县| 和林格尔县| 辽源市| 讷河市| 旬阳县| 龙江县| 南安市| 招远市| 罗甸县| 石阡县| 安塞县| 都江堰市|