<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    void

    Java安全有效的實現兩星期內自動登陸功能

    http://stonejava.javaeye.com/blog/255136

    http://www.javaeye.com/topic/130309

    http://i18n.javaeye.com/blog/130849

    =========================================

    現在很多網站都有為用戶保存登陸信息(即保存Cookie)的功能,當用戶下一次進入網站時,可以幫助用戶自動登陸,使網站顯得更加友好。筆者通過 研究ACEGI項目的自動登陸源碼,編寫了一個安全有效的實現兩星期自動登陸功能的JAVA工具類,下面是具體的實現流程和實現代碼。

      先說一下流程:

      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中的MD5碼相比較,如果相同,寫入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組合字符串的MD5碼的字符串----------------------------------------------------------------------------
    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) >> 4, 16));
    sb.append(Character.forDigit(buffer[i] & 0x0f, 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.java與DaoImplFactory.java屬于持久層相關的程序,這里就不貼出來了,讀者可根據自己需要選擇不同的持久層框架,在本程序中只要實現查詢用戶的功能就可以了

    posted on 2009-06-26 10:22 void 閱讀(494) 評論(0)  編輯  收藏 所屬分類: Java

    主站蜘蛛池模板: 国产亚洲综合视频| 国产亚洲情侣久久精品| 免费人成在线观看网站| 在线播放亚洲第一字幕| 国产区在线免费观看| 区三区激情福利综合中文字幕在线一区亚洲视频1 | 成人免费av一区二区三区| 国产偷窥女洗浴在线观看亚洲| 国产成人亚洲毛片| 免费一级毛片不卡在线播放| 白白色免费在线视频| 亚洲欧洲日产国码一级毛片| jizz免费在线观看| 亚洲国产精彩中文乱码AV| 99久久99热精品免费观看国产| 亚洲精品熟女国产| 毛片高清视频在线看免费观看| 亚洲国产成人精品无码区花野真一 | 亚洲一区免费观看| 精品亚洲AV无码一区二区三区| 日韩免费a级毛片无码a∨| 亚洲AV无码一区二区三区牲色| 亚洲成a人一区二区三区| 久久久久久久久久久免费精品| 亚洲AV中文无码乱人伦下载| 91麻豆最新在线人成免费观看| 亚洲色大成网站www久久九| 亚洲成aⅴ人片久青草影院| a级午夜毛片免费一区二区| 亚洲另类自拍丝袜第1页| 日韩免费视频在线观看| 国产特黄一级一片免费| 亚洲成AV人片久久| 俄罗斯极品美女毛片免费播放 | 国产精品免费大片| 久久久久亚洲国产| 亚洲精品国产精品乱码不卡√| 67194熟妇在线永久免费观看| 老司机午夜精品视频在线观看免费| 久久亚洲精品视频| 无码高潮少妇毛多水多水免费 |