登入幾乎是每個項目都具有的功能,記住密碼也是常見的部分,在使用者登入時,實作記住密碼的功能一般使用兩個方法來實作:
- 使用cookie,将登入資訊存入cookie,存儲在使用者本地。
- 持久化,将登入資訊存入資料庫,因為cookie存在過期,而且使用者浏覽器可能會禁用cookie,使用這個方法有效避免了這些問題。
第二種方法就不多說了,基本就是資料庫中表的CRUD的操作了,下面來說一下第一種方法。
cookie是一種WEB伺服器通過浏覽器在通路者的硬碟上存儲資訊的手段。Cookie的目的就是為使用者帶來友善,為網站帶來增值。雖然有着許多誤傳,事實上Cookie并不會造成嚴重的安全威脅。
Cookie永遠不會以任何方式執行,是以也不會帶來病毒或攻擊你的系統。另外,由于浏覽器一般隻允許存放300個Cookie,每個站點最多存放20個Cookie,每個Cookie的大小限制為4KB,是以Cookie不會塞滿你的硬碟。
例如,當我們第一次通路網站輸入使用者名密碼時,可以選擇讓系統記住使用者名密碼,下次就不用重新輸入了,這就是典型的Cookie的應用。
在讨論cookie的時候都會聯想到session,它們之間的差別和聯系如下:
-
cookie機制和session機制的差別
具體來說cookie機制采用的是在用戶端保持狀态的方案,而session機制采用的是在伺服器端保持狀态的方案。
同時我們也看到,由于在伺服器端保持狀态的方案在用戶端也需要儲存一個辨別,是以session機制可能需要借助于cookie機制來達到儲存辨別的目的,但實際上還有其他選擇。
-
會話cookie和持久cookie的差別
如果不設定過期時間,則表示這個cookie生命周期為浏覽器會話期間,隻要關閉浏覽器視窗,cookie就消失了。這種生命期為浏覽會話期的cookie被稱為會話cookie。會話cookie一般不儲存在硬碟上而是儲存在記憶體裡。
如果設定了過期時間,浏覽器就會把cookie儲存到硬碟上,關閉後再次打開浏覽器,這些cookie依然有效直到超過設定的過期時間。
存儲在硬碟上的cookie可以在不同的浏覽器程序間共享,比如兩個IE視窗。而對于儲存在記憶體的cookie,不同的浏覽器有不同的處理方式。
接下來實作一個記住密碼的功能:
<div class="form-group">
<label class="checkbox-inline">
<input type="checkbox" name="rememberMe" id="rememberMe" onclick="remember();"/>
Remember me
</label> <span class="pull-right">
</div>
//記住密碼複選框的點選事件
function remember(){
var remFlag = $("input[type='checkbox']").is(':checked');
if(remFlag==true){ //如果選中設定remFlag為true
//cookie存使用者名和密碼,回顯的是真實的使用者名和密碼,存在安全問題.
var conFlag = confirm("記錄密碼功能不宜在公共場所(如網吧等)使用,以防密碼洩露.您确定要使用此功能嗎?");
if(conFlag){ //确認标志
$("#remFlag").val(true);
}else{
$("input[type='checkbox']").removeAttr('checked');
$("#remFlag").val(false);
}
}else{ //如果沒選中設定remFlag為false
$("#remFlag").val(false);
}
}
下一次通路此頁面自動填充賬号密碼
$(document).ready(function(){
//記住密碼功能
var str = getCookie("loginInfo");
str = str.substring(,str.length-);
var username = str.split(",")[];
var password = str.split(",")[];
//自動填充使用者名和密碼
$("#username").val(username);
$("#pwd").val(password);
if(str!=null && str!=""){
$("input[type='checkbox']").attr("checked", true);
}
});
JavaScript getCookie()
//擷取cookie
function getCookie(cname) {
var name = cname + "=";
var ca = document.cookie.split(';');
for(var i=; i<ca.length; i++) {
var c = ca[i];
while (c.charAt()==' ') c = c.substring();
if (c.indexOf(name) != -) return c.substring(name.length, c.length);
}
return "";
}
背景Java對cookie的操作的封裝的工具類:
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 該類可以從浏覽器請求中提取出cookies并進行對cookis的相關操作
* @author Administrator
*
*/
public class CookiesUtil {
/**
* 根據名字擷取cookie
*
* @param request
* @param name
* cookie名字
* @return
*/
public static Cookie getCookieByName(HttpServletRequest request, String name) {
Map<String, Cookie> cookieMap = ReadCookieMap(request);
if (cookieMap.containsKey(name)) {
Cookie cookie = (Cookie) cookieMap.get(name);
return cookie;
} else {
return null;
}
}
/**
* 将cookie封裝到Map裡面
*
* @param request
* @return
*/
private static Map<String, Cookie> ReadCookieMap(HttpServletRequest request) {
Map<String, Cookie> cookieMap = new HashMap<String, Cookie>();
Cookie[] cookies = request.getCookies();
if (null != cookies) {
for (Cookie cookie : cookies) {
cookieMap.put(cookie.getName(), cookie);
}
}
return cookieMap;
}
/**
* 儲存Cookies
*
* @param response
* servlet請求
* @param value
* 儲存值
*/
public static HttpServletResponse setCookie(HttpServletResponse response, String name, String value,int time) {
// new一個Cookie對象,鍵值對為參數
Cookie cookie = new Cookie(name, value);
// tomcat下多應用共享
cookie.setPath("/");
// 如果cookie的值中含有中文時,需要對cookie進行編碼,不然會産生亂碼
try {
URLEncoder.encode(value, "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
cookie.setMaxAge(time);
// 将Cookie添加到Response中,使之生效
response.addCookie(cookie); // addCookie後,如果已經存在相同名字的cookie,則最新的覆寫舊的cookie
return response;
}
/**
* <p>删除無效cookie</p>
* <p>無效☞1.過時 2.未釋出</p>
* @param request
* @param response
* @param list
*/
@SuppressWarnings("unused")
private void delectCookieByName(HttpServletRequest request, HttpServletResponse response,String deleteKey) throws NullPointerException {
Map<String, Cookie> cookieMap = ReadCookieMap(request);
for (String key : cookieMap.keySet()) {
if(key==deleteKey && key.equals(deleteKey)) {
Cookie cookie = cookieMap.get(key);
cookie.setMaxAge();//設定cookie有效時間為0
cookie.setPath("/");//不設定存儲路徑
response.addCookie(cookie);
}
}
}
}
附加知識點:
為了在網絡傳輸上更加安全,一般對密碼進行加密之後再送出加密之後的密碼串至背景,在資料庫的使用者表中密碼這一字段直接存儲加密之後的密碼串即可,二者進行比對,判斷是否能登入成功。進行加密可以使用不可逆的MD5加密,雖然這已經是不可逆的了,安全度已經很高了,但是如果想更安全一點不被撞擊出原始值,可以自己寫一個工具類生成一定長度的随機字元串+密碼,之後再進行加密,這樣的話就算使用抓包工具得到了你的密碼串,破解出你的密碼的機率微乎其微了。
工具類生成一定長度的随機字元串
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;
public class StringUtils {
/**
* 擷取随機字元串,可用于加密 添加字元,增加保密度
*/
private static final String ALLCHAR = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
/**
* 擷取任意位的随機字元串(0-9 a-z A-Z)
*
* @param size
* 位數
* @return
*/
public static final String getRandomNum(int size) {
StringBuffer sb = new StringBuffer();
Random random = new Random();
for (int i = ; i < size; i++) {
sb.append(ALLCHAR.charAt(random.nextInt(ALLCHAR.length())));
}
return sb.toString();
}
/**
* md5加密(ITS)
*
* @param str
* @param charSet
* @return
*/
public synchronized static final String getMD5Str(String str, String charSet) { // md5加密
MessageDigest messageDigest = null;
try {
messageDigest = MessageDigest.getInstance("MD5");
messageDigest.reset();
if (charSet == null) {
messageDigest.update(str.getBytes());
} else {
messageDigest.update(str.getBytes(charSet));
}
} catch (NoSuchAlgorithmException e) {
} catch (UnsupportedEncodingException e) {
}
byte[] byteArray = messageDigest.digest();
StringBuffer md5StrBuff = new StringBuffer();
for (int i = ; i < byteArray.length; i++) {
if (Integer.toHexString( & byteArray[i]).length() == )
md5StrBuff.append("0").append(
Integer.toHexString( & byteArray[i]));
else
md5StrBuff.append(Integer.toHexString( & byteArray[i]));
}
return md5StrBuff.toString();
}
}
jsp頁面産生随機數或随機字元串
<%
//産生随機數,和密碼一起生成MD5
request.getSession().setAttribute("md5RandomKey", StringUtils.getRandomNum());
%>
表單送出時,onsubmit事件中:
//表單送出時對輸入的密碼進行加密, 避免抓包分析破解密碼
var hash = MD5($('#pwd').val()+"${md5RandomKey}");
var hash = MD5($('#pwd').val());
$('#pwd').val(hash);
好了,功德圓滿。