時候,我們需要產生一個資料,這個資料儲存了使用者的資訊,但加密後仍然有可能被人使用,即便他人不確切的瞭解詳細資料...
好比,我們在上網的時候,很多網頁都會有一個資訊,是否儲存登入資訊,以便下次可以直接登入而不必再次輸入賬戶,密碼等...而通常這樣需要Cookie儲存使用者資訊,當然,這個資訊是加密資訊,且一般都加了時間戳記等驗證資訊的...
登陸時,讀取cookie,解析cookie的資訊,以及如時間戳記等附加資訊.如果沒有時間戳記...那麼任何人只要有這個cookie,複製cookie到他的電腦中,然後登陸相同的頁面,即便盜用者並不知道使用者的資訊是什麼,也能登陸...
所以,時間戳記就類似我們所說的安全性權杖.
方式,將使用者資訊MD5加密後,再將時間戳記MD5加密,然後按照特定的處理,將加密後的使用者資訊以及時間戳記,ip地址等資訊再次處理,加密後,產生cookie儲存用戶端...這樣就避免了前面所說的安全問題...
java.security.MessageDigest,在建立安全性權杖上,比MD5更簡便.因為update方法!!!
package cn.vicky.utils;</p><p>import java.security.MessageDigest;<br />import java.security.NoSuchAlgorithmException;</p><p>/**<br /> * 令牌處理器<br /> *<br /> * @author Vicky<br /> * @emial eclipser@163.com<br /> *<br /> */<br />public class TokenProcessor {</p><p>private static TokenProcessor instance = new TokenProcessor();</p><p>private long previous;</p><p>protected TokenProcessor() {<br />}</p><p>public static TokenProcessor getInstance() {<br />return instance;<br />}</p><p>public synchronized String generateToken(String msg, boolean timeChange) {<br />try {</p><p>long current = System.currentTimeMillis();<br />if (current == previous) current++;<br />previous = current;<br />MessageDigest md = MessageDigest.getInstance("MD5");<br />md.update(msg.getBytes());<br />if (timeChange) {<br />// byte now[] = (current+"").toString().getBytes();<br />byte now[] = (new Long(current)).toString().getBytes();<br />md.update(now);<br />}<br />return toHex(md.digest());<br />} catch (NoSuchAlgorithmException e) {<br />return null;<br />}<br />}</p><p>private String toHex(byte buffer[]) {<br />StringBuffer sb = new StringBuffer(buffer.length * 2);<br />for (int i = 0; i < buffer.length; i++) {<br />sb.append(Character.forDigit((buffer[i] & 240) >> 4, 16));<br />sb.append(Character.forDigit(buffer[i] & 15, 16));<br />}</p><p>return sb.toString();<br />}<br />}<br />
測試
@Test<br />public void testGenerateToken(){</p><p>String token = new TokenProcessor().generateToken("Vicky",true);</p><p>System.err.println(token);</p><p>String token2 = new TokenProcessor().generateToken("Vicky",false);</p><p>System.err.println(token2);<br />}<br />
執行後列印:
69ff8ae72232da59a613ecc830ed7c7a
020c290593cef84aeac4ea2c269d326d
再次執行列印:
d8e38257652deaa76de81c8225801482
020c290593cef84aeac4ea2c269d326d
可見,第1列印的資料,是一直變換的.因為他加入了時間戳記
而第2條列印的資料卻是不變的,因為他只是簡單的MD5加密
這樣的安全性權杖在很多大型架構中都會涉及,比如說頂頂大名的Struts.這裡,我以servlet為執行個體,向request請求加入安全性權杖!
package cn.vicky.struts.util;</p><p>import java.security.MessageDigest;<br />import java.security.NoSuchAlgorithmException;</p><p>import javax.servlet.http.HttpServletRequest;<br />import javax.servlet.http.HttpSession;</p><p>/**<br /> *<br /> * @author Vicky<br /> * @email eclipser@163.com<br /> *<br /> */<br />public class TokenProcessor {</p><p>private static TokenProcessor instance = new TokenProcessor();</p><p>private long previous;</p><p>protected TokenProcessor() {<br />}</p><p>public static TokenProcessor getInstance() {<br />return instance;<br />}</p><p>public synchronized boolean isTokenValid(HttpServletRequest request) {<br />return isTokenValid(request, false);<br />}</p><p>public synchronized boolean isTokenValid(HttpServletRequest request,<br />boolean reset) {</p><p>HttpSession session = request.getSession(false);<br />if (session == null<br />return false;<br />String saved = (String) session<br />.getAttribute("cn.vicky.struts.action.TOKEN");<br />if (saved == null)<br />return false;</p><p>if (reset)<br />resetToken(request);<br />String token = request<br />.getParameter("cn.vicky.struts.taglib.html.TOKEN");<br />if (token == null)<br />return false;<br />else<br />return saved.equals(token);<br />}</p><p>public synchronized void resetToken(HttpServletRequest request) {<br />HttpSession session = request.getSession(false);<br />if (session == null) {<br />return;<br />} else {<br />session.removeAttribute("cn.vicky.struts.action.TOKEN");<br />return;<br />}<br />}</p><p>public synchronized void saveToken(HttpServletRequest request) {<br />HttpSession session = request.getSession();<br />String token = generateToken(request);<br />if (token != null)<br />session.setAttribute("cn.vicky.struts.action.TOKEN", token);<br />}</p><p>public synchronized String generateToken(HttpServletRequest request) {<br />HttpSession session = request.getSession();<br />return generateToken(session.getId());<br />}</p><p>public synchronized String generateToken(String id) {<br />try {</p><p>long current = System.currentTimeMillis();<br />if (current == previous)<br />current++;<br />previous = current;</p><p>// byte now[] = (current+"").toString().getBytes();<br />byte now[] = (new Long(current)).toString().getBytes();<br />MessageDigest md = MessageDigest.getInstance("MD5");</p><p>md.update(id.getBytes());<br />md.update(now);<br />System.out.println(md.digest().length);<br />return toHex(md.digest());<br />} catch (NoSuchAlgorithmException e) {<br />return null;<br />}<br />}</p><p>private String toHex(byte buffer[]) {<br />StringBuffer sb = new StringBuffer(buffer.length * 2);<br />for (int i = 0; i < buffer.length; i++) {<br />sb.append(Character.forDigit((buffer[i] & 240) >> 4, 16));<br />sb.append(Character.forDigit(buffer[i] & 15, 16));<br />}</p><p>return sb.toString();<br />}<br />}<br />