--------------------------第一個(gè):簡(jiǎn)單明了-------------------
http://www.ieee.org.cn/dispbbs.asp?boardID=41&ID=13873
代碼:
import java.security.*;
import java.security.spec.*;


class MD5_Test
{


public final static String MD5(String s)
{

char hexDigits[] =
{
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
'e', 'f'};

try
{
byte[] strTemp = s.getBytes();
MessageDigest mdTemp = MessageDigest.getInstance("MD5");
mdTemp.update(strTemp);
byte[] md = mdTemp.digest();
int j = md.length;
char str[] = new char[j * 2];
int k = 0;

for (int i = 0; i < j; i++)
{
byte byte0 = md[i];
str[k++] = hexDigits[byte0 >>> 4 & 0xf];
str[k++] = hexDigits[byte0 & 0xf];
}
return new String(str);
}

catch (Exception e)
{
return null;
}
}

public static void main(String[] args)
{
//MD5_Test aa = new MD5_Test();

System.out.print(MD5_Test.MD5("XX"));
}

-----------------第二個(gè):說(shuō)明注釋詳細(xì)---------------
http://m.tkk7.com/haogj/archive/2006/07/04/56604.html
MD5即Message-Digest Algorithm 5(信息-摘要算法5),是一種用于產(chǎn)生數(shù)字簽名的單項(xiàng)散列算法,在1991年由MIT Laboratory for Computer Science(IT計(jì)算機(jī)科學(xué)實(shí)驗(yàn)室)和RSA Data Security Inc(RSA數(shù)據(jù)安全公司)的Ronald L. Rivest教授開發(fā)出來(lái),經(jīng)由MD2、MD3和MD4發(fā)展而來(lái)。MD5算法的使用不需要支付任何版權(quán)費(fèi)用。它的作用是讓大容量信息在用數(shù)字簽名軟件簽私人密匙前被"壓縮"成一種保密的格式(將一個(gè)任意長(zhǎng)度的“字節(jié)串”通過一個(gè)不可逆的字符串變換算法變換成一個(gè)128bit的大整數(shù),換句話說(shuō)就是,即使你看到源程序和算法描述,也無(wú)法將一個(gè)MD5的值變換回原始的字符串,從數(shù)學(xué)原理上說(shuō),是因?yàn)樵嫉淖址袩o(wú)窮多個(gè),這有點(diǎn)象不存在反函數(shù)的數(shù)學(xué)函數(shù)。)
在 Java 中,java.security.MessageDigest 中已經(jīng)定義了 MD5 的計(jì)算,所以我們只需要簡(jiǎn)單地調(diào)用即可得到 MD5 的128 位整數(shù)。然后將此 128 位計(jì) 16 個(gè)字節(jié)轉(zhuǎn)換成 16 進(jìn)制表示即可。
代碼:
package com.tsinghua;


/** *//**
* MD5的算法在RFC1321 中定義
* 在RFC 1321中,給出了Test suite用來(lái)檢驗(yàn)?zāi)愕膶?shí)現(xiàn)是否正確:
* MD5 ("") = d41d8cd98f00b204e9800998ecf8427e
* MD5 ("a") = 0cc175b9c0f1b6a831c399e269772661
* MD5 ("abc") = 900150983cd24fb0d6963f7d28e17f72
* MD5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0
* MD5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b
*
* @author haogj
*
* 傳入?yún)?shù):一個(gè)字節(jié)數(shù)組
* 傳出參數(shù):字節(jié)數(shù)組的 MD5 結(jié)果字符串
*/

public class MD5
{

public static String getMD5(byte[] source)
{
String s = null;

char hexDigits[] =
{ // 用來(lái)將字節(jié)轉(zhuǎn)換成 16 進(jìn)制表示的字符
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
try

{
java.security.MessageDigest md = java.security.MessageDigest.getInstance( "MD5" );
md.update( source );
byte tmp[] = md.digest(); // MD5 的計(jì)算結(jié)果是一個(gè) 128 位的長(zhǎng)整數(shù),
// 用字節(jié)表示就是 16 個(gè)字節(jié)
char str[] = new char[16 * 2]; // 每個(gè)字節(jié)用 16 進(jìn)制表示的話,使用兩個(gè)字符,
// 所以表示成 16 進(jìn)制需要 32 個(gè)字符
int k = 0; // 表示轉(zhuǎn)換結(jié)果中對(duì)應(yīng)的字符位置

for (int i = 0; i < 16; i++)
{ // 從第一個(gè)字節(jié)開始,對(duì) MD5 的每一個(gè)字節(jié)
// 轉(zhuǎn)換成 16 進(jìn)制字符的轉(zhuǎn)換
byte byte0 = tmp[i]; // 取第 i 個(gè)字節(jié)
str[k++] = hexDigits[byte0 >>> 4 & 0xf]; // 取字節(jié)中高 4 位的數(shù)字轉(zhuǎn)換,
// >>> 為邏輯右移,將符號(hào)位一起右移
str[k++] = hexDigits[byte0 & 0xf]; // 取字節(jié)中低 4 位的數(shù)字轉(zhuǎn)換
}
s = new String(str); // 換后的結(jié)果轉(zhuǎn)換為字符串

}catch( Exception e )

{
e.printStackTrace();
}
return s;
}
}


測(cè)試代碼:
import com.tsinghua.*;
public class TestMD5


{
public static void main( String xu[] )

{ // 計(jì)算 "a" 的 MD5 代碼,應(yīng)該為:0cc175b9c0f1b6a831c399e269772661
System.out.println( MD5.getMD5("a".getBytes()) );
}
}

-----------第三個(gè):服務(wù)周到--------
MD5加密算法嚴(yán)密,安全性較高,廣泛應(yīng)用于系統(tǒng)身份驗(yàn)證、文件完整性驗(yàn)證中。Java API中java.security包中包含MessageDigest類,可以實(shí)現(xiàn)MD5算法的簡(jiǎn)單應(yīng)用,譬如將指定的普通明文轉(zhuǎn)換成MD5密碼,參考源代碼如下:
/* *************************************************************
* Project: bobToolkit <p>
* Package: bob.sec.MD5 <p>
* Filename: MD5Util.java<p>
* Created by BobChen on 2007-3-29 <p>
* ////////////////////////////////////////////////////////////
* Date Author Description
* 2007-3-29 BobChen init: object MD5Util
* ***********************************************************/
package bob.sec.MD5;
import java.security.MessageDigest;
public class MD5Util {
public final static String MD5(String s) {
char hexDigits[] = { '0', '1', '2', '3', '4',
'5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F' };
try {
byte[] btInput = s.getBytes();
MessageDigest mdInst = MessageDigest.getInstance("MD5");
mdInst.update(btInput);
byte[] md = mdInst.digest();
int j = md.length;
char str[] = new char[j * 2];
int k = 0;
for (int i = 0; i < j; i++) {
byte byte0 = md[i];
str[k++] = hexDigits[byte0 >>> 4 & 0xf];
str[k++] = hexDigits[byte0 & 0xf];
}
return new String(str);
}
catch (Exception e) {
// e.printStackTrace();
return null;
}
}
public static void main(String[] args) {
System.out.print(MD5Util.MD5("AusITcim#1485"));
}
}
---------- 運(yùn)行 ----------
EF277661A4C821C9007ACB52E1D883EC
輸出完成 (耗時(shí) 0 秒) - 正常終止
----------------------JSP頁(yè)面調(diào)用-------------------------------
----------
String u_password=new String(request.getParameter("u_password").getBytes("ISO-8859-1"));
u_password=(new MD5Util().MD5(u_password));
---------
String u_id=new String(request.getParameter("u_id").getBytes("ISO-8859-1"));
String u_password=new String(request.getParameter("u_password").getBytes("ISO-8859-1"));
u_password=(new MD5Util().MD5(u_password));
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1621920
----------第四個(gè):java MD5算法返回?cái)?shù)字型字串 --------
常有人問及MD5算法為何有些程序片斷返回完全數(shù)字型結(jié)果而有些返回?cái)?shù)字與字母的混合字串。
其實(shí)兩種返回結(jié)果只是因?yàn)榧用芙Y(jié)果的不同顯示形式,Blog中已經(jīng)有.Net的實(shí)現(xiàn),在此附加JAVA實(shí)現(xiàn),供參考。
JAVA的標(biāo)準(zhǔn)類庫(kù)理論上功能也很強(qiáng)大,但由于虛擬機(jī)/運(yùn)行時(shí)的實(shí)現(xiàn)太多,加之版本差異,有些代碼在不同環(huán)境下運(yùn)行會(huì)出現(xiàn)奇怪的異常結(jié)果,尤其以涉及字符集的操作為甚。
package com.bee.framework.common;
import java.security.MessageDigest;
public class MD5Encrypt {
public MD5Encrypt() {
}
private final static String[] hexDigits = {
"0", "1", "2", "3", "4", "5", "6", "7",
"8", "9", "a", "b", "c", "d", "e", "f"};
/**
* 轉(zhuǎn)換字節(jié)數(shù)組為16進(jìn)制字串
* @param b 字節(jié)數(shù)組
* @return 16進(jìn)制字串
*/
public static String byteArrayToString(byte[] b) {
StringBuffer resultSb = new StringBuffer();
for (int i = 0; i < b.length; i++) {
//resultSb.append(byteToHexString(b[i]));//若使用本函數(shù)轉(zhuǎn)換則可得到加密結(jié)果的16進(jìn)制表示,即數(shù)字字母混合的形式
resultSb.append(byteToNumString(b[i]));//使用本函數(shù)則返回加密結(jié)果的10進(jìn)制數(shù)字字串,即全數(shù)字形式
}
return resultSb.toString();
}
private static String byteToNumString(byte b) {
int _b = b;
if (_b < 0) {
_b = 256 + _b;
}
return String.valueOf(_b);
}
private static String byteToHexString(byte b) {
int n = b;
if (n < 0) {
n = 256 + n;
}
int d1 = n / 16;
int d2 = n % 16;
return hexDigits[d1] + hexDigits[d2];
}
public static String MD5Encode(String origin) {
String resultString = null;
try {
resultString = new String(origin);
MessageDigest md = MessageDigest.getInstance("MD5");
resultString =
byteArrayToString(md.digest(resultString.getBytes()));
}
catch (Exception ex) {
}
return resultString;
}
public static void main(String[] args) {
MD5Encrypt md5encrypt = new MD5Encrypt();
System.out.println(MD5Encode("10000000"));
}
}
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=470562
----------第五個(gè):理論---------
MD5的Java Bean實(shí)現(xiàn)
2001 年 3 月 01 日
編者的話:
雖然 MD5 簽名算法在 jdk 中早已實(shí)現(xiàn)(如 MessageDigest類),但作者從 MD5 的原理分析講述 MD5 具體算法的 Java實(shí)現(xiàn)并給出一個(gè)完整的示例程序,我想這對(duì)我們的讀者來(lái)說(shuō)還是會(huì)有很多幫助的。
MD5簡(jiǎn)介
MD5的全稱是Message-Digest Algorithm 5,在90年代初由MIT的計(jì)算機(jī)科學(xué)實(shí)驗(yàn)室和RSA Data Security Inc發(fā)明,經(jīng)MD2、MD3和MD4發(fā)展而來(lái)。
Message-Digest泛指字節(jié)串(Message)的Hash變換,就是把一個(gè)任意長(zhǎng)度的字節(jié)串變換成一定長(zhǎng)的大整數(shù)。請(qǐng)注意我使用了“字節(jié)串”而不是“字符串”這個(gè)詞,是因?yàn)檫@種變換只與字節(jié)的值有關(guān),與字符集或編碼方式無(wú)關(guān)。
MD5將任意長(zhǎng)度的“字節(jié)串”變換成一個(gè)128bit的大整數(shù),并且它是一個(gè)不可逆的字符串變換算法,換句話說(shuō)就是,即使你看到源程序和算法描述,也無(wú)法將一個(gè)MD5的值變換回原始的字符串,從數(shù)學(xué)原理上說(shuō),是因?yàn)樵嫉淖址袩o(wú)窮多個(gè),這有點(diǎn)象不存在反函數(shù)的數(shù)學(xué)函數(shù)。
MD5的典型應(yīng)用是對(duì)一段Message(字節(jié)串)產(chǎn)生fingerprint(指紋),以防止被“篡改”。舉個(gè)例子,你將一段話寫在一個(gè)叫readme.txt文件中,并對(duì)這個(gè)readme.txt產(chǎn)生一個(gè)MD5的值并記錄在案,然后你可以傳播這個(gè)文件給別人,別人如果修改了文件中的任何內(nèi)容,你對(duì)這個(gè)文件重新計(jì)算MD5時(shí)就會(huì)發(fā)現(xiàn)。如果再有一個(gè)第三方的認(rèn)證機(jī)構(gòu),用MD5還可以防止文件作者的“抵賴”,這就是所謂的數(shù)字簽名應(yīng)用。
MD5還廣泛用于加密和解密技術(shù)上,在很多操作系統(tǒng)中,用戶的密碼是以MD5值(或類似的其它算法)的方式保存的,用戶Login的時(shí)候,系統(tǒng)是把用戶輸入的密碼計(jì)算成MD5值,然后再去和系統(tǒng)中保存的MD5值進(jìn)行比較,而系統(tǒng)并不“知道”用戶的密碼是什么。
一些黑客破獲這種密碼的方法是一種被稱為“跑字典”的方法。有兩種方法得到字典,一種是日常搜集的用做密碼的字符串表,另一種是用排列組合方法生成的,先用MD5程序計(jì)算出這些字典項(xiàng)的MD5值,然后再用目標(biāo)的MD5值在這個(gè)字典中檢索。
即使假設(shè)密碼的最大長(zhǎng)度為8,同時(shí)密碼只能是字母和數(shù)字,共26+26+10=62個(gè)字符,排列組合出的字典的項(xiàng)數(shù)則是P(62,1)+P(62,2)….+P(62,8),那也已經(jīng)是一個(gè)很天文的數(shù)字了,存儲(chǔ)這個(gè)字典就需要TB級(jí)的磁盤組,而且這種方法還有一個(gè)前提,就是能獲得目標(biāo)賬戶的密碼MD5值的情況下才可以。
在很多電子商務(wù)和社區(qū)應(yīng)用中,管理用戶的Account是一種最常用的基本功能,盡管很多Application Server提供了這些基本組件,但很多應(yīng)用開發(fā)者為了管理的更大的靈活性還是喜歡采用關(guān)系數(shù)據(jù)庫(kù)來(lái)管理用戶,懶惰的做法是用戶的密碼往往使用明文或簡(jiǎn)單的變換后直接保存在數(shù)據(jù)庫(kù)中,因此這些用戶的密碼對(duì)軟件開發(fā)者或系統(tǒng)管理員來(lái)說(shuō)可以說(shuō)毫無(wú)保密可言,本文的目的是介紹MD5的Java Bean的實(shí)現(xiàn),同時(shí)給出用MD5來(lái)處理用戶的Account密碼的例子,這種方法使得管理員和程序設(shè)計(jì)者都無(wú)法看到用戶的密碼,盡管他們可以初始化它們。但重要的一點(diǎn)是對(duì)于用戶密碼設(shè)置習(xí)慣的保護(hù)。
有興趣的讀者可以從這里取得MD5也就是RFC 1321的文本。http://www.ietf.org/rfc/rfc1321.txt
實(shí)現(xiàn)策略
MD5的算法在RFC1321中實(shí)際上已經(jīng)提供了C的實(shí)現(xiàn),我們其實(shí)馬上就能想到,至少有兩種用Java實(shí)現(xiàn)它的方法,第一種是,用Java語(yǔ)言重新寫整個(gè)算法,或者再說(shuō)簡(jiǎn)單點(diǎn)就是把C程序改寫成Java程序。第二種是,用JNI(Java Native Interface)來(lái)實(shí)現(xiàn),核心算法仍然用這個(gè)C程序,用Java類給它包個(gè)殼。
但我個(gè)人認(rèn)為,JNI應(yīng)該是Java為了解決某類問題時(shí)的沒有辦法的辦法(比如與操作系統(tǒng)或I/O設(shè)備密切相關(guān)的應(yīng)用),同時(shí)為了提供和其它語(yǔ)言的互操作性的一個(gè)手段。使用JNI帶來(lái)的最大問題是引入了平臺(tái)的依賴性,打破了SUN所鼓吹的“一次編寫到處運(yùn)行”的Java好處。因此,我決定采取第一種方法,一來(lái)和大家一起嘗試一下“一次編寫到處運(yùn)行”的好處,二來(lái)檢驗(yàn)一下Java 2現(xiàn)在對(duì)于比較密集的計(jì)算的效率問題。
實(shí)現(xiàn)過程
限于這篇文章的篇幅,同時(shí)也為了更多的讀者能夠真正專注于問題本身,我不想就某一種Java集成開發(fā)環(huán)境來(lái)介紹這個(gè)Java Bean的制作過程,介紹一個(gè)方法時(shí)我發(fā)現(xiàn)步驟和命令很清晰,我相信有任何一種Java集成環(huán)境三天以上經(jīng)驗(yàn)的讀者都會(huì)知道如何把這些代碼在集成環(huán)境中編譯和運(yùn)行。用集成環(huán)境講述問題往往需要配很多屏幕截圖,這也是我一直對(duì)集成環(huán)境很頭疼的原因。我使用了一個(gè)普通的文本編輯器,同時(shí)使用了Sun公司標(biāo)準(zhǔn)的JDK 1.3.0 for Windows NT。
其實(shí)把C轉(zhuǎn)換成Java對(duì)于一個(gè)有一定C語(yǔ)言基礎(chǔ)的程序員并不困難,這兩個(gè)語(yǔ)言的基本語(yǔ)法幾乎完全一致.我大概花了一個(gè)小時(shí)的時(shí)間完成了代碼的轉(zhuǎn)換工作,我主要作了下面幾件事:
- 把必須使用的一些#define的宏定義變成Class中的final static,這樣保證在一個(gè)進(jìn)程空間中的多個(gè)Instance共享這些數(shù)據(jù)
- 刪去了一些無(wú)用的#if define,因?yàn)槲抑魂P(guān)心MD5,這個(gè)推薦的C實(shí)現(xiàn)同時(shí)實(shí)現(xiàn)了MD2 MD3和 MD4,而且有些#if define還和C不同編譯器有關(guān)
- 將一些計(jì)算宏轉(zhuǎn)換成final static 成員函數(shù)。
- 所有的變量命名與原來(lái)C實(shí)現(xiàn)中保持一致,在大小寫上作一些符合Java習(xí)慣的變化,計(jì)算過程中的C函數(shù)變成了private方法(成員函數(shù))。
- 關(guān)鍵變量的位長(zhǎng)調(diào)整
- 定義了類和方法
需要注意的是,很多早期的C編譯器的int類型是16 bit的,MD5使用了unsigned long int,并認(rèn)為它是32bit的無(wú)符號(hào)整數(shù)。而在Java中int是32 bit的,long是64 bit的。在MD5的C實(shí)現(xiàn)中,使用了大量的位操作。這里需要指出的一點(diǎn)是,盡管Java提供了位操作,由于Java沒有unsigned類型,對(duì)于右移位操作多提供了一個(gè)無(wú)符號(hào)右移:>>>,等價(jià)于C中的 >> 對(duì)于unsigned 數(shù)的處理。
因?yàn)镴ava不提供無(wú)符號(hào)數(shù)的運(yùn)算,兩個(gè)大int數(shù)相加就會(huì)溢出得到一個(gè)負(fù)數(shù)或異常,因此我將一些關(guān)鍵變量在Java中改成了long類型(64bit)。我個(gè)人認(rèn)為這比自己去重新定義一組無(wú)符號(hào)數(shù)的類同時(shí)重載那些運(yùn)算符要方便,同時(shí)效率高很多并且代碼也易讀,OO(Object Oriented)的濫用反而會(huì)導(dǎo)致效率低下。
限于篇幅,這里不再給出原始的C代碼,有興趣對(duì)照的讀者朋友可以去看RFC 1321。 MD5.java源代碼
測(cè)試
在RFC 1321中,給出了Test suite用來(lái)檢驗(yàn)?zāi)愕膶?shí)現(xiàn)是否正確:
MD5 ("") = d41d8cd98f00b204e9800998ecf8427e
MD5 ("a") = 0cc175b9c0f1b6a831c399e269772661
MD5 ("abc") = 900150983cd24fb0d6963f7d28e17f72
MD5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0
MD5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b
……
|
這些輸出結(jié)果的含義是指:空字符串””的MD5值是d41d8cd98f00b204e9800998ecf8427e,字符串”a”的MD5值是
0cc175b9c0f1b6a831c399e269772661……
編譯并運(yùn)行我們的程序:
javac –Cd . MD5.java
java beartool.MD5
|
為了將來(lái)不與別人的同名程序沖突,我在我的程序的第一行使用了package beartool;
因此編譯命令 javac ?Cd . MD5.java 命令在我們的工作目錄下自動(dòng)建立了一個(gè) beartool 目錄,目錄下放著編譯成功的 MD5.class
我們將得到和Test suite同樣的結(jié)果。當(dāng)然還可以繼續(xù)測(cè)試你感興趣的其它MD5變換,例如:
將給出1234的MD5值。
可能是我的計(jì)算機(jī)知識(shí)是從Apple II和Z80單板機(jī)開始的,我對(duì)大寫十六進(jìn)制代碼有偏好,如果您想使用小寫的Digest String只需要把byteHEX函數(shù)中的A、B、C、D、E、F改成a、b、 c、d、e、f就可以了。
MD5據(jù)稱是一種比較耗時(shí)的計(jì)算,我們的Java版MD5一閃就算出來(lái)了,沒遇到什么障礙,而且用肉眼感覺不出來(lái)Java版的MD5比C版的慢。
為了測(cè)試它的兼容性,我把這個(gè)MD5.class文件拷貝到我的另一臺(tái)Linux+IBM JDK 1.3的機(jī)器上,執(zhí)行后得到同樣結(jié)果,確實(shí)是“一次編寫到處運(yùn)行了”。
Java Bean簡(jiǎn)述
現(xiàn)在,我們已經(jīng)完成并簡(jiǎn)單測(cè)試了這個(gè)Java Class,我們文章的標(biāo)題是做一個(gè)Java Bean。
其實(shí)普通的Java Bean很簡(jiǎn)單,并不是什么全新的或偉大的概念,就是一個(gè)Java的Class,盡管 Sun規(guī)定了一些需要實(shí)現(xiàn)的方法,但并不是強(qiáng)制的。而EJB(Enterprise Java Bean)無(wú)非規(guī)定了一些必須實(shí)現(xiàn)(非常類似于響應(yīng)事件)的方法,這些方法是供EJB Container使用(調(diào)用)的。
在一個(gè)Java Application或Applet里使用這個(gè)bean非常簡(jiǎn)單,最簡(jiǎn)單的方法是你要使用這個(gè)類的源碼工作目錄下建一個(gè)beartool目錄,把這個(gè)class文件拷貝進(jìn)去,然后在你的程序中import beartool.MD5就可以了。最后打包成.jar或.war是保持這個(gè)相對(duì)的目錄關(guān)系就行了。
Java還有一個(gè)小小的好處是你并不需要摘除我們的MD5類中那個(gè)main方法,它已經(jīng)是一個(gè)可以工作的Java Bean了。Java有一個(gè)非常大的優(yōu)點(diǎn)是她允許很方便地讓多種運(yùn)行形式在同一組代碼中共存,比如,你可以寫一個(gè)類,它即是一個(gè)控制臺(tái)Application和GUI Application,同時(shí)又是一個(gè)Applet,同時(shí)還是一個(gè)Java Bean,這對(duì)于測(cè)試、維護(hù)和發(fā)布程序提供了極大的方便,這里的測(cè)試方法main還可以放到一個(gè)內(nèi)部類中。
這里講述了把測(cè)試和示例代碼放在一個(gè)內(nèi)部靜態(tài)類的好處,是一種不錯(cuò)的工程化技巧和途徑。
把Java Bean裝到JSP里
正如我們?cè)诒疚拈_頭講述的那樣,我們對(duì)這個(gè)MD5 Bean的應(yīng)用是基于一個(gè)用戶管理,這里我們假設(shè)了一個(gè)虛擬社區(qū)的用戶login過程,用戶的信息保存在數(shù)據(jù)庫(kù)的個(gè)名為users的表中。這個(gè)表有兩個(gè)字段和我們的這個(gè)例子有關(guān),userid :char(20)和pwdmd5 :char(32),userid是這個(gè)表的Primary Key,pwdmd5保存密碼的MD5串,MD5值是一個(gè)128bit的大整數(shù),表示成16進(jìn)制的ASCII需要32個(gè)字符。
這里給出兩個(gè)文件, login.html是用來(lái)接受用戶輸入的form, login.jsp 用來(lái)模擬使用MD5 Bean的login過程。
為了使我們的測(cè)試環(huán)境簡(jiǎn)單起見,我們?cè)贘SP中使用了JDK內(nèi)置的JDBC-ODBC Bridge Driver,community是ODBC的DSN的名字,如果你使用其它的JDBC Driver,替換掉login.jsp中的
Connection con= DriverManager.getConnection("jdbc:odbc:community", "", "");
|
即可。
login.jsp的工作原理很簡(jiǎn)單,通過post接收用戶輸入的UserID和Password,然后將Password變換成MD5串,然后在users表中尋找UserID和pwdmd5,因?yàn)閁serID是users表的Primary Key,如果變換后的pwdmd5與表中的記錄不符,那么SQL查詢會(huì)得到一個(gè)空的結(jié)果集。
這里需要簡(jiǎn)單介紹的是,使用這個(gè)Bean只需要在你的JSP應(yīng)用程序的WEB-INF/classes下建立一個(gè)beartool目錄,然后將MD5.class拷貝到那個(gè)目錄下就可以了。如果你使用一些集成開發(fā)環(huán)境,請(qǐng)參考它們的deploy工具的說(shuō)明。在JSP使用一個(gè)java Bean關(guān)鍵的一句聲明是程序中的第2行:
<jsp:useBean id='oMD5' scope='request' class='beartool.MD5'/>
|
這是所有JSP規(guī)范要求JSP容器開發(fā)者必須提供的標(biāo)準(zhǔn)Tag。
id=實(shí)際上是指示JSP Container創(chuàng)建Bean的實(shí)例時(shí)用的實(shí)例變量名。在后面的<%和%>之間的Java程序中,你可以引用它。在程序中可以看到,通過 pwdmd5=oMD5.getMD5ofStr (password) 引用了我們的MD5 Java Bean提供的唯一一個(gè)公共方法: getMD5ofStr。
Java Application Server執(zhí)行.JSP的過程是先把它預(yù)編譯成.java(那些Tag在預(yù)編譯時(shí)會(huì)成為java語(yǔ)句),然后再編譯成.class。這些都是系統(tǒng)自動(dòng)完成和維護(hù)的,那個(gè).class也稱為Servlet。當(dāng)然,如果你愿意,你也可以幫助Java Application Server去干本該它干的事情,自己直接去寫Servlet,但用Servlet去輸出HTML那簡(jiǎn)直是回到了用C寫CGI程序的惡夢(mèng)時(shí)代。
如果你的輸出是一個(gè)復(fù)雜的表格,比較方便的方法我想還是用一個(gè)你所熟悉的HTML編輯器編寫一個(gè)“模板”,然后在把JSP代碼“嵌入”進(jìn)去。盡管這種JSP代碼被有些專家指責(zé)為“空心粉”,它的確有個(gè)缺點(diǎn)是代碼比較難管理和重復(fù)使用,但是程序設(shè)計(jì)永遠(yuǎn)需要的就是這樣的權(quán)衡。我個(gè)人認(rèn)為,對(duì)于中、小型項(xiàng)目,比較理想的結(jié)構(gòu)是把數(shù)據(jù)表示(或不嚴(yán)格地稱作WEB界面相關(guān))的部分用JSP寫,和界面不相關(guān)的放在Bean里面,一般情況下是不需要直接寫Servlet的。
如果你覺得這種方法不是非常的OO(Object Oriented),你可以繼承(extends)它一把,再寫一個(gè)bean把用戶管理的功能包進(jìn)去。
到底能不能兼容?
我測(cè)試了三種Java應(yīng)用服務(wù)器環(huán)境,Resin 1.2.3、Sun J2EE 1.2、IBM WebSphere 3.5,所幸的是這個(gè)Java Bean都沒有任何問題,原因其實(shí)是因?yàn)樗鼉H僅是個(gè)計(jì)算程序,不涉及操作系統(tǒng),I/O設(shè)備。其實(shí)用其它語(yǔ)言也能簡(jiǎn)單地實(shí)現(xiàn)它的兼容性的,Java的唯一優(yōu)點(diǎn)是,你只需提供一個(gè)形態(tài)的運(yùn)行碼就可以了。請(qǐng)注意“形態(tài)”二字,現(xiàn)在很多計(jì)算結(jié)構(gòu)和操作系統(tǒng)除了語(yǔ)言本身之外都定義了大量的代碼形態(tài),很簡(jiǎn)單的一段C語(yǔ)言核心代碼,轉(zhuǎn)換成不同形態(tài)要考慮很多問題,使用很多工具,同時(shí)受很多限制,有時(shí)候?qū)W習(xí)一種新的“形態(tài)”所花費(fèi)的精力可能比解決問題本身還多。比如光Windows就有EXE、Service、的普通DLL、COM DLL以前還有OCX等等等等,在Unix上雖說(shuō)要簡(jiǎn)單一些,但要也要提供一個(gè).h定義一大堆宏,還要考慮不同平臺(tái)編譯器版本的位長(zhǎng)度問題。我想這是Java對(duì)我來(lái)說(shuō)的一個(gè)非常重要的魅力吧。
login.html代碼:
<html>
<head>
<title>Login</title>
</head>
<body>
<form method="POST" action="login.jsp">
<p>UserID:<input type="text" name="UserID" size="20">
Password:<input type="password" name="Password" size="20"></p>
<p><input type="submit" value="Login" name="Login"></p>
</form>
</body>
</html>

login.jsp代碼:

<%
@ page language='java' %>
<jsp:useBean id='oMD5' scope='request' class='beartool.MD5'/>
<%@ page import='java.util.*'%>
<%@ page import='java.sql.*'%>
<html>
<body>
<pre>
<%
String userid = request.getParameter("UserID"); //接受UserID
String password = request.getParameter("Password"); //接受Password
String pwdmd5 = oMD5.getMD5ofStr(password); //變換密碼
PrintWriter rp = response.getWriter();
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Connection con = DriverManager.getConnection("jdbc:odbc:community", "", "");
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("select * from users where userID ='"
+userid+"' and pwdmd5= '" + pwdmd5+"'" );
if (rs.next())
{
rp.print("Login OK");
}
else
{
rp.print("Login Fail");
}
stmt.close();
con.close();
%>

posted on 2008-01-30 15:21
lk 閱讀(755)
評(píng)論(0) 編輯 收藏 所屬分類:
j2se