• Applet 数字签名技术完全攻略


     

         这里说声对不起大家。毕竟2几年前,我想写这篇文章,但因为他才懒得一直没有写。同时也给自己的东西好。前些日子我老大让我又搞这个东西发现我曾经的资料没留,又凭着自己印象从新来过。但发现网上写的东西真的有些肤浅,实在说只是去。毕竟我们是程序猿,不是学生了,怎么也点多想些东西哦,于是将自己总结的东西写下来,留给刚開始学习的人一些启发好了。通过学习一下内容您将具备通过server全然訪问本地client的能力。不在受不论什么权限的困扰,(非常多文章都写须要改 client本地的策略文件。事实上根本不是必需,仅仅要client点了俺们的数字签名,俺们可就什么都能干了) ~oo~    

         简单说下 Applet 数字签名是怎么回事: 就是applet 利用 jdk 里的 工具   $JAVA_HOME/bin 以下的 一堆 exe 文件进行 server訪问本地client的安全签名。

    假设想让客户真的信任你的applet签名,能够花几百大元去 CA 旗下的 versign 公司购买可信任的 签名证书。

         本文主要以Tomcat为中间件,讲述详细签名步骤。当中 $JAVA_HOME 为 jdk 的安装文件夹、$TOMCAT_HOME为 Tomcat 的安装文件夹

          实现Applet的签名过程例如以下:

          1. 设定环境变量   $JAVA_HOME (方便在windows 系统下的不论什么一个文件夹都能够直接 使用     $JAVA_HOME/bin 下的 exe 命令。当中的exe 包含 keytool.exe,jarsigner.exe和HtmlConverter.exe )。

         2. 将 $TOMCAT_HOME 下 webapps 文件夹的ROOT文件夹拷贝一份,删除没实用的垃圾东西改成自己的web应用名字。比如 : webapplet  将须要签名的jar 复制到 $TOMCAT_HOME/webapps/webapplet  下,在这里须要 注意一点:签名jar 包 就要对 整个 project 引用涉及到的 jar 包都进行签名。否则少签一个你都执行不起来的。

        3. 建立一个測试的html页面 applet.html

          <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

          比如:  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: // &apos;w&apos;
    			archiveName = "winLib.zip";
    			break;
    
    		case 108: // &apos;l&apos;
    			archiveName = "linuxLib.zip";
    			break;
    
    		case 115: // &apos;s&apos;
    			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 != &apos;w&apos;)
    			//              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();
    	//			}
    	//	}
    }
    
  • 相关阅读:
    DevExpress ASP.NET 使用经验谈(5)-通过ASPxGridView实现CRUD操作
    DevExpress ASP.NET 使用经验谈(4)-CriteriaOperator的使用
    DevExpress ASP.NET 使用经验谈(3)-XPO对象的使用(使用指定数据连接)
    DevExpress ASP.NET 使用经验谈(2)-XPO对象的使用(使用默认数据连接)
    DevExpress ASP.NET 使用经验谈(1)-XPO模型的创建
    C#堆栈原理(我有两个例子测试你到底会不会)
    C# static 干货全解析
    C# 链接 SQLite问题汇总
    EFCore AsNoTracking方法不能使用的问题;EFCore 如何取消跟踪
    2019-1-3 每日一记
  • 原文地址:https://www.cnblogs.com/yxwkf/p/4570009.html
Copyright © 2020-2023  润新知