這裏說聲對不起你們。畢竟2幾年前,我想寫這篇文章,但由於他才懶得一直沒有寫。同時也給本身的東西好。前些日子我老大讓我又搞這個東西發現我曾經的資料沒留,又憑着本身印象重新來過。但發現網上寫的東西真的有些膚淺,實在說只是去。畢竟咱們是程序猿,不是學生了,怎麼也點多想些東西哦,因而將本身總結的東西寫下來,留給剛開始學習的人一些啓發好了。經過學習一下內容您將具有經過server全然訪問本地client的能力。不在受不論什麼權限的困擾,(很是多文章都寫需要改 client本地的策略文件。事實上根本不是必需,僅僅要client點了俺們的數字簽名,俺們可就什麼都能幹了) ~oo~ html
簡單說下 Applet 數字簽名是怎麼回事: 就是applet 利用 jdk 裏的 工具 $JAVA_HOME/bin 如下的 一堆 exe 文件進行 server訪問本地client的安全簽名。java
假設想讓客戶真的信任你的applet簽名,可以花幾百大元去 CA 旗下的 versign 公司購買可信任的 簽名證書。linux
本文主要以Tomcat爲中間件,講述詳細簽名步驟。當中 $JAVA_HOME 爲 jdk 的安裝文件夾、$TOMCAT_HOME爲 Tomcat 的安裝文件夾web
實現Applet的簽名過程例如如下: 面試
1. 設定環境變量 $JAVA_HOME (方便在windows 系統下的不論什麼一個文件夾都可以直接 使用 $JAVA_HOME/bin 下的 exe 命令。當中的exe 包含 keytool.exe,jarsigner.exe和HtmlConverter.exe )。apache
2. 將 $TOMCAT_HOME 下 webapps 文件夾的ROOT文件夾拷貝一份,刪除沒實用的垃圾東西改爲本身的web應用名字。好比 : webapplet 將需要簽名的jar 複製到 $TOMCAT_HOME/webapps/webapplet 下,在這裏需要 注意一點:簽名jar 包 就要對 整個 project 引用涉及到的 jar 包都進行簽名。不然少籤一個你都執行不起來的。windows
3. 創建一個測試的html頁面 applet.html api
<APPLET
CODEBASE = "."
CODE = "com.aspire.reportPlatform.webagent.WebAgentApplet.class"
ARCHIVE ="applet.jar"
NAME = "TestApplet"
WIDTH = 400
HEIGHT = 300
HSPACE = 0
VSPACE = 0
ALIGN = middle
>
</APPLET> 安全
4. 打開 cmd 命令提示符,在$TOMCAT_HOME/webapps/webapplet 下執行 HtmlConverter app
好比: F:/appletTomcat/webapps/webapplet>HtmlConverter
彈出個窗體。在窗體中輸入需要轉換的 html文件 好比我剛纔寫的applet.html,轉換完的東西 寫jsp 也相同適用的。
轉換完例如如下所看到的 :
<!--"CONVERTED_APPLET"-->
<!-- HTML CONVERTER -->
<object
classid = "clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"
codebase = "http://java.sun.com/update/1.5.0/jinstall-1_5-windows-i586.cab#Version=5,0,0,1"
WIDTH = 400 HEIGHT = 300 NAME = "TestApplet" ALIGN = middle VSPACE = 0 HSPACE = 0 >
<PARAM NAME = CODE VALUE = "com.aspire.reportPlatform.webagent.WebAgentApplet.class" >
<PARAM NAME = CODEBASE VALUE = "." >
<PARAM NAME = ARCHIVE VALUE = "applet.jar,commons-codec-1.3.jar,commons-httpclient-3.1.jar,commons-logging.jar,dom4j.jar,FlowMetaData.jar,ibatis-2.3.2.715.jar,jgraph.jar,log4j-1.2.9.jar,MetaDataManage.jar,ojdbc14.jar,RDPCommon.jar,swing-layout-1.0.jar,ws-commons-util-1.0.1.jar,xmlrpc-client-3.1.jar,xmlrpc-common-3.1.jar" >
<PARAM NAME = NAME VALUE = "TestApplet" >
<param name = "type" value = "application/x-java-applet;version=1.5">
<param name = "scriptable" value = "false">
<comment>
<embed
type = "application/x-java-applet;version=1.5" /
CODE = "com.aspire.reportPlatform.webagent.WebAgentApplet.class" /
JAVA_CODEBASE = "." /
ARCHIVE = "applet.jar" /
NAME = "TestApplet" /
WIDTH = 400 /
HEIGHT = 300 /
ALIGN = middle /
VSPACE = 0 /
HSPACE = 0
scriptable = false
pluginspage = "http://java.sun.com/products/plugin/index.html#download">
<noembed>
</noembed>
</embed>
</comment>
</object>
<!--
<APPLET CODE = "com.aspire.reportPlatform.webagent.WebAgentApplet.class" JAVA_CODEBASE = "." ARCHIVE = "applet.jar" WIDTH = 400 HEIGHT = 300 NAME = "TestApplet" ALIGN = middle VSPACE = 0 HSPACE = 0>
</APPLET>
-->
<!--"END_CONVERTED_APPLET"-->
這裏需要注意一個東西。上面有寫 <PARAM NAME = ARCHIVE VALUE = "applet.jar.. 那塊。正常轉換完了 僅僅會寫到 applet.jar , 後面是我直接把 applet 需要引用的 jar 包直接加上去的,再次反覆提醒 : 在這裏也要把 需要簽名關聯的所有jar 包都寫上去,不然前功盡棄!
6. 爲了省事本身寫個bat文件玩,來進行簽名,好比我寫的 applet.bat
內容例如如下:
keytool -genkey -keystore pepper.store -alias pepper keytool -export -keystore pepper.store -alias pepper -file pepper.cert jarsigner -keystore pepper.store applet.jar pepper jarsigner -keystore pepper.store commons-codec-1.3.jar pepper jarsigner -keystore pepper.store commons-httpclient-3.1.jar pepper jarsigner -keystore pepper.store commons-logging.jar pepper jarsigner -keystore pepper.store dom4j.jar pepper jarsigner -keystore pepper.store FlowMetaData.jar pepper jarsigner -keystore pepper.store ibatis-2.3.2.715.jar pepper jarsigner -keystore pepper.store jgraph.jar pepper jarsigner -keystore pepper.store log4j-1.2.9.jar pepper jarsigner -keystore pepper.store MetaDataManage.jar pepper jarsigner -keystore pepper.store ojdbc14.jar pepper jarsigner -keystore pepper.store RDPCommon.jar pepper jarsigner -keystore pepper.store swing-layout-1.0.jar pepper jarsigner -keystore pepper.store ws-commons-util-1.0.1.jar pepper jarsigner -keystore pepper.store xmlrpc-client-3.1.jar pepper jarsigner -keystore pepper.store xmlrpc-common-3.1.jar pepper
解說下 裏面的意思 :
keytool -genkey -keystore pepper.store -alias pepper #建立pepper.store 密鑰庫文件,這個密鑰庫的別名爲 pepper
輸入上面那段話後。會提示輸入password jdk 默以爲 changeit ,這個password可以改動,怎樣改動請到網上查下就好,我記不清列,但建議不改,因爲有時因爲改了password jdk1.4 會離奇的很差用。。。
password輸完 ,就輸入些相應的 一些簽名信息。
F:/appletTomcat/webapps/applet>keytool -genkey -keystore pepper.store -alias pepper
輸入keystorepassword: changeit
您的名字與姓氏是什麼?
[Unknown]: LEe
您的組織單位名稱是什麼?
[Unknown]: aspire
您的組織名稱是什麼?
[Unknown]: aspire
您所在的城市或區域名稱是什麼?
[Unknown]: sz
您所在的州或省份名稱是什麼?
[Unknown]: gd
該單位的兩字母國家代碼是什麼
[Unknown]: cn
CN=LEe, OU=aspire, O=aspire, L=sz, ST=gd, C=cn 正確嗎?
[否]: y
輸入<pepper>的主password
(假設和 keystore password一樣,按回車):
輸入password庫導出證書的password,爲了偷懶上面 那個 我直接 按 回車列。。。
keytool -export -keystore pepper.store -alias pepper -file pepper.cert 依據生成的密鑰庫導出 pepper.cert 證書,輸入password changeit , 說一句 這塊可以 輸入 上步你本身設定 password庫導出證書的password(假設不是 changeit)
jarsigner -keystore pepper.store applet.jar pepper 爲 applet.jar 簽名,輸入 證書password 我這塊可以寫 changeit, 如下的 jar 包 都是反覆輸入這裏很少說了。over ! 寫到你們應該可以玩本身的簽名了,我還有個讀取文件方面的經驗: 那就是原本在 application 裏寫的好好的東西到了 applet 上就都很差用了。緣由是applet 的載入機制就是 把 server上簽名的jar 包都下載到 client的 暫時文件夾裏,文名都給改了。。。
這個暫時文件夾好比個人 : C:/Documents and Settings/x_lixin_a/Application Data/Sun/Java/Deployment/cache/javapi/v1.0/jar
因此我在搞讀文件的東西都把 配置文件下載到了client本地。比例如如下載到
System.getProperty("java.io.tmpdir") 的文件夾如下,到這裏去讀就不會出問題列,日誌有時也會出問題,建議直接寫 ***.log ,這樣在執行時會把 生成的日誌文件 扔到桌面,事實上仍是不提倡有日誌,畢竟用戶看見這個東西不爽。。。
順便把俺寫的 applet 讓你們看看吧,
思路 : 1 . 將需要讀取的 配置文件下載到本地。 2 . 執行 main 類。跑application 。
測試 : 在 ie 中輸入 http://localhost:8080/webapplet 看到有 applet 彈出一個框點擊執行就成,順便提一句: 查看錯誤可以注意下右下角任務欄出現的大茶壺圖標, 執行applet 都會啓動這個東西。點擊右鍵看到有 打開主控制檯的選項。點這個選項,彈出一個對話框,這個對話框 就可以查看你的 簽名 哪裏出問題了,用 System.out.println() 都可以打到這個控制檯上,但建議先在本地的 Eclipse project裏 執行經過在拿到上面試。 後記 : 寫到這裏你們應該都會知道怎麼實現 applet 數字簽名了,假設有什麼疑問可以直接在 csdn抓我,或者發送郵件到 lixin_0411@126.com, 但願有log 日誌那塊配置 更好解決方式的必定要告訴我撒,互相交流下哇。認爲我寫的這篇文章還可以 朋友但願能幫我頂起來,但願一年之後我將不會在看到網上寫的那篇垃圾文章(現在那篇文章寫的哪都是。根本不能解決這個問題。) ~oo~
代碼例如如下:
package com.aspire.reportPlatform.webagent; import java.applet.Applet; import java.awt.Color; import java.awt.Container; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.net.URL; import java.net.URLConnection; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import javax.swing.JApplet; import com.aspire.rdp.flowdesinger.LogonDialog; public class WebAgentApplet extends JApplet { public static Applet m_runningApplet = null; protected char m_osPrefix; // private OctetSeqHolder resp = null; private Container contentPane = null; public static String agentID; private static Long agentLongID; // private static final String DLLFOLDERPATH= System.getProperty("user.dir") // ; // private static final String // DLLFOLDERPATH=System.getProperty("java.home")+File.separator+"lib"+File.separator+"ext"; private static final String DLLFOLDERPATH = System.getProperty("java.home") + File.separator + "bin"; String TEMP_DIR = System.getProperty("java.io.tmpdir"); private int result = 1; private int count = 0; public static String certerIP = null; private String nickname = null; public static String serverFullAddress; /** * @throws java.lang.AbstractMethodError */ public void init() { certerIP = getParameter("centerAddress"); certerIP = new String("192.168.168.111"); System.err.println("centerIP is" + certerIP); System.out.println(" user.dir = "+ System.getProperty("user.dir")); nickname = getParameter("nickname"); serverFullAddress = String.valueOf(getCodeBase()); m_osPrefix = System.getProperty("os.name").toLowerCase().charAt(0); // installLibraries(); DirectoryVO directoryVOArray[] = createDirectories(); for(int i=0;i< directoryVOArray.length;i++) { installConfigResources(directoryVOArray[i]); } drawPane(); LogonDialog logonDialog = new LogonDialog(); logonDialog.setVisible(true); try { // add(panel); if (m_runningApplet != null) { StatusPanel.getStatusPanelInstance().setStatus((byte) 11); } else { m_runningApplet = this; // webAgent = new WebAgent(); // initializeCommunication(webAgent); StatusPanel.getStatusPanelInstance() .setStatus((byte) 11); // if (result == 0) { // StatusPanel.getStatusPanelInstance() // .setStatus((byte) 0); // } else { // StatusPanel.getStatusPanelInstance() // .setStatus((byte) 8); // } // heartbeatInfo = new HeartbeatInfo(); // new Thread(heartbeatInfo).start(); // webAgent.initialize(webAgent, this); // sendHeartInfo(); } } catch (Exception _ex) { // LogFile.getInstance().print(0, "WebAgentApplet.init()", // " Applet initial Failed !"); // _ex.printStackTrace(); StatusPanel.getStatusPanelInstance().setStatus((byte) 8); _ex.printStackTrace(); // destroy(); } } private DirectoryVO[] createDirectories() { DirectoryVO[] directoryVOArray = new DirectoryVO[3]; DirectoryVO directoryVO = new DirectoryVO(); String config = TEMP_DIR+"rdp"; File configFile=new File(config); if(!configFile.exists()) { configFile.mkdir(); } String plugins = config + File.separator + "plugins"; File pluginsFile= new File(plugins); if(!pluginsFile.exists()) { pluginsFile.mkdir(); } String email = plugins + File.separator + "email"; File emailFile= new File(email); if(!emailFile.exists()) { emailFile.mkdir(); } directoryVO.setPathName(email); directoryVO.setZipName("emailPlugins.zip"); directoryVOArray[0] = directoryVO; String images = config + File.separator + "images"; File imagesFile = new File(images); if(!imagesFile.exists()) { imagesFile.mkdir(); } String cfg = config + File.separator + "cfg"; File cfgFile = new File(cfg); if(!cfgFile.exists()) { cfgFile.mkdir(); } DirectoryVO directoryVO1 = new DirectoryVO(); directoryVO1.setZipName("images.zip"); directoryVO1.setPathName(images); directoryVOArray[1] = directoryVO1; DirectoryVO directoryVO2 = new DirectoryVO(); directoryVO2.setZipName("cfg.zip"); directoryVO2.setPathName(cfg); directoryVOArray[2] = directoryVO2; return directoryVOArray; } private void installConfigResources(DirectoryVO directoryVO){ String archivePath = String.valueOf(getCodeBase()) + "native" + "/" + directoryVO.getZipName(); System.out.println(" archivePath = " + archivePath); ZipInputStream zis = null; ZipEntry entry = null; URLConnection con = null; try { con = (new URL(archivePath)).openConnection(); con.setUseCaches(false); con.connect(); zis = new ZipInputStream(con.getInputStream()); while ((entry = zis.getNextEntry()) != null){ installConfigResource(zis, entry.getName(),directoryVO.getPathName()); } } catch (IOException ioe) { StatusPanel.getStatusPanelInstance().setStatus((byte) 8); ioe.printStackTrace(); // LogFile.getInstance().print(0, // "WebAgentApplet.installLibraries()", // "install have IOException "); }catch(Exception e){ e.printStackTrace(); }finally { con = null; try { zis.close(); } catch (IOException e) { // TODO 本身主動生成 catch 塊 e.printStackTrace(); } } } private void installConfigResource(ZipInputStream archive, String configResourceName,String path){ BufferedOutputStream out = null; byte buffer[] = new byte[1024]; int count = 0; String configFullPathName = path + File.separator + configResourceName; try { out = new BufferedOutputStream( new FileOutputStream(configFullPathName)); while ((count = archive.read(buffer)) > 0) out.write(buffer, 0, count); out.close(); } catch (IOException e) { e.printStackTrace(); }catch(Exception e){ e.printStackTrace(); }finally{ try { out.close(); } catch (IOException e1) { // TODO 本身主動生成 catch 塊 e1.printStackTrace(); } } } public void drawPane() { contentPane = getContentPane(); contentPane.setBackground(Color.white); contentPane.add(StatusPanel.getStatusPanelInstance()); } public void destroy() { try { if (m_runningApplet == this) { // webAgent.testManagerModule.close(); // StatusControl.getStatusControlInstance().notifyToCenter(StatusControlModuleConstant.AGENT_DOWN_SUCCESS,agentLongID); // appletCommunicateModule.stop(); } } catch (Exception e) { // LogFile.getInstance().print(0, "WebAgentApplet.destroy()", // "UnknownHostException : cannot destory applet "); e.printStackTrace(); } finally { System.exit(0); System.err.println("in applet close !!!!"); } } private void installLibraries() { String archivePath = String.valueOf(getCodeBase()) + "native"; System.err.println(getCodeBase()); ZipInputStream zis = null; ZipEntry entry = null; URLConnection con = null; String archiveName; switch (m_osPrefix) { case 119: // 'w' archiveName = "winLib.zip"; break; case 108: // 'l' archiveName = "linuxLib.zip"; break; case 115: // 's' archiveName = "solarisLib.zip"; break; default: archiveName = "winLib.zip"; break; } try { con = (new URL(archivePath + "/" + archiveName)).openConnection(); con.setUseCaches(false); con.connect(); zis = new ZipInputStream(con.getInputStream()); while ((entry = zis.getNextEntry()) != null){ installLibrary(zis, entry.getName()); } } catch (IOException ioe) { StatusPanel.getStatusPanelInstance().setStatus((byte) 8); ioe.printStackTrace(); // LogFile.getInstance().print(0, // "WebAgentApplet.installLibraries()", // "install have IOException "); }catch(Exception e){ e.printStackTrace(); }finally { con = null; try { zis.close(); } catch (IOException e) { // TODO 本身主動生成 catch 塊 e.printStackTrace(); } } } private void installLibrary(ZipInputStream archive, String dllName) { BufferedOutputStream out = null; byte buffer[] = new byte[1024]; int count = 0; String dllFullPathName = DLLFOLDERPATH + File.separator + dllName; System.out.println(" dllFullPathName = " + dllFullPathName); try { out = new BufferedOutputStream( new FileOutputStream(dllFullPathName)); while ((count = archive.read(buffer)) > 0) out.write(buffer, 0, count); out.close(); // if(m_osPrefix != 'w') // CommandLineUtility.runCommand("chmod 0775 " + dllFullPathName); } catch (IOException e) { e.printStackTrace(); // LogFile.getInstance().print(0, "WebAgentApplet.installLibrary()", // "install single Library failed "); // exitDueToException(e, "copying a native library file into JRE // directory"); }catch(Exception e){ e.printStackTrace(); }finally{ try { out.close(); } catch (IOException e1) { // TODO 本身主動生成 catch 塊 e1.printStackTrace(); } } } // private void installLogFile(){ // try { // String // logProperties=System.getProperty("java.home")+File.separator+"bin"+File.separator+"log4j.properties"; // File f=new File(logProperties); // f.createNewFile(); // FileOutputStream fopt=new FileOutputStream(f); // String firstParagraph=new String("##LOGGERS##/r/n#define a logger named // SEAMISLogger/r/nlog4j.rootLogger=INFO,file/r/n/r/n"); // fopt.write(firstParagraph.getBytes()); // String senondParagraph=new String("##APPENDERS##/r/n#define an appender // named file,which is set to be a // RollingFileAppender/r/nlog4j.appender.file=org.apache.log4j.RollingFileAppender/r/n"+"log4j.appender.file.File="+System.getProperty("java.home")+File.separator+"bin"+File.separator+"agentlog.txt"+"/r/n/r/n"); // fopt.write(senondParagraph.getBytes()); // String thirdParagraph=new String("##LAYOUTS##/r/n#assign a SimpleLayout // to file // appender/r/nlog4j.appender.file.layout=org.apache.log4j.SimpleLayout/r/n"); // fopt.write(thirdParagraph.getBytes()); // fopt.close(); // } catch (FileNotFoundException e) { // // TODO 生成本身主動 catch 塊 // e.printStackTrace(); // } catch (IOException e) { // // TODO 生成本身主動 catch 塊 // e.printStackTrace(); // } // } }