关键字 resin 虚拟主机 java.policy
提示
首先不要用root运行java.
本文适合启用安全机制的resin.
启用java的安全沙箱
默认resin是没有启用安全机制的,虚拟主机用户可以随意读取系统文件,例如/etc/passwd等.
开启安全机制很简单,在resin.conf中的resin节点下加上:
<security-manager/>
重新运行resin,默认的安全沙箱就打开了,不过此时会发现什么程序都运行不了了.此时用的是java默认提供的java.policy.
浏览resin的文档,提供了一个简单的policy http://www.caucho.com/resin-3.0/security/securitymanager.xtp .
(建议粗略阅读一下 http://www.caucho.com/resin-3.0/security/index.xtp 的所有章节 )
了解安全沙箱
默认的policy或者resin提供的policy是远远不够的,所以要定义自己的policy.
在开始之前,也许你应该阅读一下java doc中的security的文档,了解一下Permission的机制和类型.
本文不对policy的语法和Permission运行机制做解释.
本文也不对用户签名做解释,因为除非特殊要求,也是没有这个要求的.
除了java本身提供的Permission,一些类库也提供了一些Permission,例如ognl本身也提供了一个,如果用到这些类库,也要进行相应的设置.
默认的语法类似:
grant codeBase "file:/home/testuser/-" {
permission java.io.FilePermission "/tmp/abc", "read";
};
java提供的权限类型有:
java.security.AllPermission 所有权限的集合
java.security.SecurityPermission policy安全控制方面的
java.security.UnresolvedPermission
java.awt.AWTPermission
java.io.FilePermission 文件权限,包括读写,删除,执行
java.io.SerializablePermission 序列化(次第读写)
java.lang.reflect.ReflectPermission 反射
java.lang.RuntimePermission 运行时
java.net.NetPermission 网络
java.net.SocketPermission
java.sql.SQLPermission 数据库sql
java.util.PropertyPermission 系统/环境属性
java.util.logging.LoggingPermission 日志控制
javax.net.ssl.SSLPermission 安全连接
javax.security.auth.AuthPermission 认证
javax.security.auth.PrivateCredentialPermission
javax.security.auth.kerberos.DelegationPermission
javax.security.auth.kerberos.ServicePermission
javax.sound.sampled.AudioPermission
目录匹配提示:
*表示所有文件
-表示所有文件及其子目录下的文件
设置resin的policy
要启用自定义的policy,在/etc/init.d/resin中修改EXE对应的一行,加入参数:
EXE="$RESIN_HOME/bin/httpd.sh -Djava.security.policy=/web/resin/policy/resin.policy "
你的policy保存在resin目录下的resin.policy,或者其他地方也可,但是要有适当的权限.
policy设置之路
resin或者说java的policy设置起来非常麻烦,总之没有直观的方法.我的方法就是设置一个,重新启动resin,访问页面,然后看日志,然后修改policy.
其中很多地方有很多疑问,还没有得到解决,一些policy明明看到已经包含在别的policy里,但是又必须单独设置,非常奇怪.
总之觉得是对底层运行机制不熟悉造成的吧.
如果有熟悉的人,不妨指点一二.
最后获取的resin.policy如下:
// java和resin类赋予所有权限
grant codeBase "file:${java.home}/lib/-" {
permission java.security.AllPermission;
};
grant codeBase "file:${java.home}/jre/lib/-" {
permission java.security.AllPermission;
};
grant codeBase "file:${java.home}/lib/ext/-" {
permission java.security.AllPermission;
};
grant codeBase "file:${java.home}/jre/lib/ext/-" {
permission java.security.AllPermission;
};
grant codeBase "file:${resin.home}/lib/-" {
permission java.security.AllPermission;
};
// 所有用户拥有的权限.
grant {
//read all property 可以读所有属性
permission java.util.PropertyPermission "*", "read";
// Permission "enableSubstitution"
permission java.io.SerializablePermission "enableSubstitution";
//reflect 可以使用反射,spring,hibernate很多地方都用了反射
permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
//runtime 这个很多,自己一个一个理解吧,根据程序不同,需要增减
permission java.lang.RuntimePermission "accessClassInPackage.*";
permission java.lang.RuntimePermission "getClassLoader";
permission java.lang.RuntimePermission "accessDeclaredMembers";
permission java.lang.RuntimePermission "modifyThreadGroup";
permission java.lang.RuntimePermission "setContextClassLoader";
permission java.lang.RuntimePermission "setIO";
permission java.lang.RuntimePermission "stopThread";
permission java.lang.RuntimePermission "createClassLoader";
permission java.lang.RuntimePermission "getProtectionDomain";
permission java.lang.RuntimePermission "defineClassInPackage";
//如果用到jce
permission java.security.SecurityPermission "putProviderProperty.SunJCE";
permission java.security.SecurityPermission "insertProvider.SunJCE";
//用到日志,需要设置
permission java.util.logging.LoggingPermission "control";
//访问1024以上的端口,如果程序没用到,可以删除
permission java.net.SocketPermission "localhost:1024-", "listen";
// Required for OpenJMX
permission java.lang.RuntimePermission "getAttribute";
// Allow read of JAXP compliant XML parser debug
permission java.util.PropertyPermission "jaxp.debug", "read";
//ognl invoke if use ognl 如果用到ognl,必须加上
permission ognl.OgnlInvokePermission "invoke.*";
};
grant {
//access mysql,if should access other database,add them 访问mysql的
permission java.net.SocketPermission "localhost:3306","connect";
//why read? 这个有疑问的,不加不行啊
permission java.io.FilePermission "${resin.home}/-", "read";
permission java.io.FilePermission "${java.home}/-", "read";
//tmp file,don't worry delete,write because you only can modify your files. 这个是读写临时文件的
permission java.io.FilePermission "/tmp/-","read,write,delete";
permission java.io.FilePermission "/tmp","read,write,delete";
};
//如果有多个虚拟主机,一些目录可以合并到一个目录,不用写多个了
grant {
//why? don't know!!! (both in classpath) 因为classpath里有这个,就得加上?
permission java.io.FilePermission ".","read";
// 因为classpath里有这个,就得加上?
permission java.io.FilePermission "/jdk5/lib/tools.jar","read";
//should have read ,who read?! 这个奇怪哦
permission java.io.FilePermission "/home/testuser/html", "read";
permission java.io.FilePermission "/home/testuser/html/-", "read";
//for resin temp-dir and jsp compile(work-dir) 临时目录
permission java.io.FilePermission "/home/testuser/worktmp/-", "read,write,delete";
//why resin will delete files for jsp compile in this directory? don't know 这个不知道,反正特奇怪
permission java.io.FilePermission "/home/testuser/html/_jsp/-", "read,write,delete";
};
//for one user 对一个用户的特殊设置
grant codeBase "file:/home/testuser/-" {
//这个用户可以读写,删除自己的文件,例如用程序生成静态文件.
permission java.io.FilePermission "/home/testuser/-", "read,write,delete";
};
经过一番折磨,我的网站终于在resin下运行起来了,尽管还有很多疑问!
如果你熟悉这些问题,请告诉我 :)