我们知道Java applet在浏览器中运行时默认情况下是不能访问本地资源的,比如读写客户端电脑上的文件。这是Java的安全沙箱机制,简单说就是有一组安全检查规则,要通过检查之后才能访问特定资源。不过在企业应用中这种安全机制有时候并不是十分必要,这里我们就讨论一下在企业应用中突破沙箱检查的方案。
当然,很多朋友会说,这太简单了,只需要改一下java.policy就可以了,授予程序对所有权限就可以了,就像下面这样:
grant {
permission java.security.AllPermission;
};
没错,这样确实可以使客户端applet有权限访问任何资源,但是这个方案有个很实际的问题:java.policy是位于每个客户端电脑的jre目录下的,如果要修改,那么就需要通知每一个使用该系统的用户,并指导他们做相应操作。这对于搞IT的用户来说是小菜一碟,但对一般业务人员来说却是个额外的工作,这样的发布方式很难被人认可。
另一个方案——对applet进行签名,用户访问时系统会弹出安全提示框,用户如果信任该程序,点击确认就相当于赋予了这个客户端小程序访问本地资源的权限。这是个很典雅的方案,体现了系统安全和对用户权利的尊重!具体做法大致如下:
1、编写applet,编译并打成jar包
2、对jar包签名
这一步首先要产生证书,利用jdk提供的工具,执行类似下面的命令:
keytool -genkey -keystore d:\mykeys.store -alias test -validity 300
根据系统提示执行完这个命令后会生成一个证书库,上例是:mykeys.store,-validity 300是证书有效期为300天的意思,接下来用这个证书库中的证书给jar包签名,仍然是jdk的工具,命令类似下面:
jarsigner -keystore d:\mykeys.store d:\applet.jar test
3、把applet.jar发布到应用服务器
这个看似完美的方案实际也有一点问题,很多时候我们并不希望把客户端程序都打到一个jar包里,那么多个jar包就需要分别签名,每次修改完客户端程序,都要重新打包和签名,不然就只有applet能访问本地资源。我们不想这么麻烦,甚至我们有时都不希望对客户端代码打包,这时候签名就不好实现了。那么如何解决这个问题呢,看下面这招。
既然applet已经被用户授权,那么是否可以在applet里改变安全管理器(SecurityManager)?实验证明是可以的!只需要继承SecurityManager类,创建自己的安全管理器类,然后覆盖checkPermission方法,允许访问任何资源。在applet的init方法中调用System.setSecurityManager把安全管理器设置为我们自己的就一切OK了!
至此,我们彻底突破了沙箱检查,而且客户体验很好,完美的方案!