posts - 32, comments - 153, trackbacks - 0, articles - 0
            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

          利用JNI調用C/C++方法實現從控制臺輸入密碼

          Posted on 2007-02-24 22:06 Zou Ang 閱讀(3675) 評論(6)  編輯  收藏 所屬分類:

          最近看到一個問題,如何用Java實現從控制臺輸入密碼?
          本來以為是很簡單的問題,查了一下發現Java居然沒提供這樣一個方法。目前實現的方式有2個,一個是利用JNI來調用C/C++方法,另一個是使用多線程。
          下面是使用JNI的方法:
          首先,寫出我們的Java類:


          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("..");來加載本地類庫,PasswordDLL是文件名,不需要加dll后綴,系統會自動辨認。

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

          /* ?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

          然后,我們需要寫一個cpp文件來實現
          JNIEXPORT?jstring?JNICALL?Java_JNIPasswordReader_readPassword??(JNIEnv?*,?jobject);
          接口。
          于是,我寫了一個PasswordDLL.cpp文件,內容如下:

          // ?這是主?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來生成對應的dll文件,在生成之前,需要把$JDK_HOME/include/jni.h和$JDK_HOME/include/win32/jni_md.h這兩個文件copy到Microsoft Visio Studio 8/VC/include目錄下,我就在這里卡了大概1個小時,一直說找不到jni.h文件

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

          關于JNI的更詳細內容,可以參考:
          《在Windows中實現Java本地方法》http://www.ibm.com/developerworks/cn/java/jnimthds/index.html

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


          評論

          # re: 利用JNI調用C/C++方法實現Java中從控制臺輸入密碼  回復  更多評論   

          2007-02-24 22:55 by 喜來樂哈哈
          JDK6.0有一個新類Console,可以解決這個問題

          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()返回一個null。比如輸入被重定向。具體的看JDK6的API Doc
          http://java.sun.com/javase/6/docs/api/java/io/Console.html

          # re: 利用JNI調用C/C++方法實現從控制臺輸入密碼  回復  更多評論   

          2007-02-24 23:03 by 喜來樂哈哈
          不好意思,剛在你裝載的文章里看到我寫的方法。我想你應該是知道這種方法的。

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

          # re: 利用JNI調用C/C++方法實現從控制臺輸入密碼  回復  更多評論   

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

          # re: 利用JNI調用C/C++方法實現從控制臺輸入密碼  回復  更多評論   

          2007-02-25 10:30 by 喜來樂哈哈
          @Zou Ang
          同意你的觀點, 本地代碼是最后一個選擇,實在沒法才用.

          # re: 利用JNI調用C/C++方法實現從控制臺輸入密碼[未登錄]  回復  更多評論   

          2007-03-14 10:48 by java愛好者
          Sun的網站以前有篇文章是講jdk6之前如何處理密碼輸入,該文建議的解決方案是用多線程來處理,一個線程專門刷新屏幕輸入,防止密碼被顯示。

          # re: 利用JNI調用C/C++方法實現從控制臺輸入密碼  回復  更多評論   

          2007-03-14 10:55 by Zou Ang
          @java愛好者
          這種方法好像在比較慢的機器上會閃爍
          主站蜘蛛池模板: 溧阳市| 武乡县| 汉寿县| 安达市| 平山县| 余江县| 轮台县| 黑山县| 贵定县| 张北县| 麻阳| 云安县| 汝阳县| 宁河县| 高碑店市| 安化县| 阿荣旗| 荆门市| 鸡泽县| 宣汉县| 讷河市| 剑川县| 商丘市| 富顺县| 巴楚县| 大化| 三都| 论坛| 晋宁县| 华池县| 乌兰察布市| 微山县| 新乡县| 高州市| 新安县| 资溪县| 建德市| 达尔| 汽车| 黔南| 大新县|