posts - 32, comments - 153, trackbacks - 0, articles - 0
            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          最近看到一個(gè)問(wèn)題,如何用Java實(shí)現(xiàn)從控制臺(tái)輸入密碼?
          本來(lái)以為是很簡(jiǎn)單的問(wèn)題,查了一下發(fā)現(xiàn)Java居然沒(méi)提供這樣一個(gè)方法。目前實(shí)現(xiàn)的方式有2個(gè),一個(gè)是利用JNI來(lái)調(diào)用C/C++方法,另一個(gè)是使用多線(xiàn)程。
          下面是使用JNI的方法:
          首先,寫(xiě)出我們的Java類(lèi):


          public ? class ?JNIPasswordReader? {

          ????
          private ? native ?String?readPassword();
          ????
          static {
          ????????System.loadLibrary(
          " PasswordDLL " );
          ????}

          ????
          /**
          ?????*?
          @param ?args
          ?????
          */

          ????
          public ? static ? void ?main(String[]?args)? {
          ????????
          // ?TODO?Auto-generated?method?stub
          ????????JNIPasswordReader?reader? = ? new ?JNIPasswordReader();
          ????????String?pwd?
          = ?reader.readPassword();
          ????????System.out.println(
          " \nYour?Password?is: " ? + ?pwd);
          ????}


          }

          這一段使用System.loadLiberary("..");來(lái)加載本地類(lèi)庫(kù),PasswordDLL是文件名,不需要加dll后綴,系統(tǒng)會(huì)自動(dòng)辨認(rèn)。

          編譯成JNIPasswordReader.class以后,使用
          javah -jni JNIPasswordReader
          命令,生成一個(gè)JNIPasswordReader.h文件,文件內(nèi)容如下:

          /* ?DO?NOT?EDIT?THIS?FILE?-?it?is?machine?generated? */
          #include?
          < jni.h >
          /* ?Header?for?class?JNIPasswordReader? */

          #ifndef?_Included_JNIPasswordReader
          #define ?_Included_JNIPasswordReader
          #ifdef?__cplusplus
          extern ? " C " ? {
          #endif
          /*
          ?*?Class:?????JNIPasswordReader
          ?*?Method:????readPassword
          ?*?Signature:?()Ljava/lang/String;
          ?
          */

          JNIEXPORT?jstring?JNICALL?Java_JNIPasswordReader_readPassword
          ??(JNIEnv?
          * ,?jobject);

          #ifdef?__cplusplus
          }

          #endif
          #endif

          然后,我們需要寫(xiě)一個(gè)cpp文件來(lái)實(shí)現(xiàn)
          JNIEXPORT?jstring?JNICALL?Java_JNIPasswordReader_readPassword??(JNIEnv?*,?jobject);
          接口。
          于是,我寫(xiě)了一個(gè)PasswordDLL.cpp文件,內(nèi)容如下:

          // ?這是主?DLL?文件。
          #include? " stdafx.h "
          #include?
          " JNIPasswordReader.h "
          #include?
          < iostream >
          #include?
          < iomanip >
          #include?
          < conio.h >
          using ? namespace ?std;

          /*
          ?*?Class:?????JNIPasswordReader
          ?*?Method:????readPassword
          ?*?Signature:?()V
          ?
          */

          JNIEXPORT?jstring?JNICALL?Java_JNIPasswordReader_readPassword
          ??(JNIEnv?
          * ?env,?jobject) {
          ??????
          char ?str[ 20 ]? = ? { 0 } ;?
          ????jstring?jstr;
          ????
          char ?ch;
          ????
          char ? * pstr? = ?str;
          ????
          while ( true )
          ????
          {
          ????????ch?
          = ?getch();
          ????????
          if (isdigit(ch) || isalpha(ch))
          ????????
          {
          ????????????cout
          << " * " ;
          ????????????
          * pstr ++ ? = ?ch;
          ????????}

          ????????
          else ? if (ch? == ? ' \b ' ? && ?pstr? > ?str)
          ????????
          {
          ????????????
          * ( -- pstr)? = ? 0 ;
          ????????????cout
          << " \b?\b " ;
          ????????}

          ????????
          else ? if (ch? == ? 0x0A ? || ?ch? == ? 0x0D )
          ????????
          {
          ????????????
          break ;
          ????????}

          ????}

          ????jstr?
          = ?env -> NewStringUTF(str);
          ????
          return ?jstr;
          }

          我使用VS2005來(lái)生成對(duì)應(yīng)的dll文件,在生成之前,需要把$JDK_HOME/include/jni.h和$JDK_HOME/include/win32/jni_md.h這兩個(gè)文件copy到Microsoft Visio Studio 8/VC/include目錄下,我就在這里卡了大概1個(gè)小時(shí),一直說(shuō)找不到j(luò)ni.h文件

          然后就可以使用VS2005來(lái)生成dll了,生成好對(duì)應(yīng)的PasswordDLL.dll以后,把該dll文件放到系統(tǒng)變量PATH能找到的地方,比如windows/system32/或者jdk/bin目錄,我是放到JDK_HOME/bin下面了
          放好以后,
          執(zhí)行java JNIPasswordReader
          就可以輸入密碼了。

          關(guān)于JNI的更詳細(xì)內(nèi)容,可以參考:
          《在Windows中實(shí)現(xiàn)Java本地方法》http://www.ibm.com/developerworks/cn/java/jnimthds/index.html

          我的Password.dll文件
          http://www.aygfsteel.com/Files/richardeee/PasswordDLL.zip


          評(píng)論

          # re: 利用JNI調(diào)用C/C++方法實(shí)現(xiàn)Java中從控制臺(tái)輸入密碼  回復(fù)  更多評(píng)論   

          2007-02-24 22:55 by 喜來(lái)樂(lè)哈哈
          JDK6.0有一個(gè)新類(lèi)Console,可以解決這個(gè)問(wèn)題

          Console console = System.console();
          if (console != null) {
          String user = new String(console.readLine("Enter username:"));
          String pwd = new String(console.readPassword("Enter passowrd:"));
          console.printf("User is :" + user + "\n");
          console.printf("Password is: " + pwd + "\n");
          } else {
          System.out.println("Console is unavailable");
          }

          但是在某些情況下System.console()返回一個(gè)null。比如輸入被重定向。具體的看JDK6的API Doc
          http://java.sun.com/javase/6/docs/api/java/io/Console.html

          # re: 利用JNI調(diào)用C/C++方法實(shí)現(xiàn)從控制臺(tái)輸入密碼  回復(fù)  更多評(píng)論   

          2007-02-24 23:03 by 喜來(lái)樂(lè)哈哈
          不好意思,剛在你裝載的文章里看到我寫(xiě)的方法。我想你應(yīng)該是知道這種方法的。

          是不是這種方法有不符合你的要求的地方?

          # re: 利用JNI調(diào)用C/C++方法實(shí)現(xiàn)從控制臺(tái)輸入密碼  回復(fù)  更多評(píng)論   

          2007-02-25 08:09 by Zou Ang
          @喜來(lái)樂(lè)哈哈
          呵呵,你的意思是我用JNI么?首先我的JDK版本是5.0的,其次我在寫(xiě)這個(gè)之前還真沒(méi)見(jiàn)到您的那篇JNI文章……其實(shí)解決密碼輸入的最好方法我覺(jué)得還是利用JDK6.0的特性,畢竟把Java跟本地代碼綁在一塊還是不太好

          # re: 利用JNI調(diào)用C/C++方法實(shí)現(xiàn)從控制臺(tái)輸入密碼  回復(fù)  更多評(píng)論   

          2007-02-25 10:30 by 喜來(lái)樂(lè)哈哈
          @Zou Ang
          同意你的觀點(diǎn), 本地代碼是最后一個(gè)選擇,實(shí)在沒(méi)法才用.

          # re: 利用JNI調(diào)用C/C++方法實(shí)現(xiàn)從控制臺(tái)輸入密碼[未登錄](méi)  回復(fù)  更多評(píng)論   

          2007-03-14 10:48 by java愛(ài)好者
          Sun的網(wǎng)站以前有篇文章是講jdk6之前如何處理密碼輸入,該文建議的解決方案是用多線(xiàn)程來(lái)處理,一個(gè)線(xiàn)程專(zhuān)門(mén)刷新屏幕輸入,防止密碼被顯示。

          # re: 利用JNI調(diào)用C/C++方法實(shí)現(xiàn)從控制臺(tái)輸入密碼  回復(fù)  更多評(píng)論   

          2007-03-14 10:55 by Zou Ang
          @java愛(ài)好者
          這種方法好像在比較慢的機(jī)器上會(huì)閃爍
          主站蜘蛛池模板: 富平县| 昆明市| 普宁市| 波密县| 紫阳县| 屏边| 汝南县| 贵州省| 乌苏市| 宁城县| 志丹县| 斗六市| 时尚| 馆陶县| 襄汾县| 繁昌县| 霍山县| 瓦房店市| 道真| 黄梅县| 开平市| 安溪县| 新民市| 台南市| 凤冈县| 天台县| 额敏县| 青州市| 达孜县| 比如县| 辽宁省| 微山县| 河曲县| 方城县| 宁武县| 华安县| 清新县| 西充县| 洛浦县| 沁水县| 岚皋县|