这两天忽然收到cs部门的反馈说一个项目出问题了,一看,噢噢噢,原来是几年前做的一个Applet的项目,在客户端无论使用什么浏览器都无法正常运行,我检查了一下,异常信息如下:
java.security.AccessControlException: access denied (java.io.FilePermission "<<ALL FILES>>", "execute")...
.....<其他信息省略>
这个问题在开发的时候也曾经遇到过,后来签名后解决了,但是最近为啥又冒出来了呢?奇怪....
我又找了N台机器,不同版本的浏览器(ie7,8,9...Cheome, Firefox....)都测了一遍发现一个问题:
1. 与浏览器无关,而是与jre的版本有关;
2. jre版本高于1.6.0_20的都不能正常运行,低于该版本的都可以正常运行(我的是JRE 版本 1.6.0_29-b11,不能运行);
如何解决呢?于是我找了Oracle里N多相关的文档,比如:
http://java.sun.com/developer/onlineTraining/Programming/JDCBook/signed.html(签名Applet)
http://docs.oracle.com/javase/1.4.2/docs/guide/security/permissions.html(Permissions in the JavaTM 2 SDK)
等等,都没啥进展。我尝试了如下方法:
1. 定义私有policy文件的方法;
2. 修改Java默认安全策略文件(不太安全), ${java.home}/lib/security/java.security文件,增加授权方式;
都没起作用(可能是我没弄对?),但是我们不能让每一个客户都去修改他们自己的安全策略文件,毕竟不是每一个人都那么专业,客户也不会愿意接受这种方式的。
问题解决:
后来在翻阅文档后发现了一个重要的方法,可以很快速的解决我的问题,那就是:使用AccessController.doPrivileged提升代码权限!如果不期望客户端修改JRE中的安全配置,可以选择在代码中提升,而这个就是我所期待的!
在客户端弹出的jdk的对话框中只要用户点击信任,运行按钮,也就是说如果信任此签名,将可以执行此代码:AccessController.doPrivileged(...),Applet权限也将得到提升。
具体示例代码如下:
private String runCmd(){ String result = AccessController.doPrivileged(new PrivilegedAction<String>() { @Override public String run() { String res = null; //TODO like 'Runtime.getRuntime().exec(cmd)' etc..... return res; } }); return result; }
别忘了,最后需要做的是重新打jar包,签名,然后将证书和keystore文件,jar文件重新发布到服务器测试:)
补充:
之前也曾写过一篇文章《关于JS调用Applet的执行权限的问题》(http://blog.csdn.net/faye0412/article/details/4566400),里面提到了使用SwingUtilities.invokeLater(new Runnable()...的方式,但是这种方法只能解决之前的签名和Applet假死的情况,不能解决现在遇到的这种情况,所以,最好的方式是结合这两种方法使用。问题完美解决!!