策略管理器要读取相应的策略文件,这些文件包含了将代码来源映射为权限的指令。下面是一个典型的策略文件:
grant codeBase "http://www.horstmann.com/classes" {
permission java.security.FilePermission "/tmp/*", "read,write";
};
该文件给所有下载自http://www.horstmann.com/classes的代码授予在/tmp目录下读取和写入文件的权限。
可以将策略文件安装在标准位置上。默认情况下,有两个位置可以安装策略文件:
l <JAVA_HOME>/lib/security/java.security。<JAVA_HOME> 引用 java.home 系统属性的值,并指定 JRE 的安装目录。
l 用户主目录的 .java.policy 文件。
可以在java.security配置文件中修改这些文件的位置,默认位置设定为:
policy.url.1=file:${java.home}/lib/security/java.policy
policy.url.2=file:${user.home}/.java.policy
如果你将策略文件存储到文件系统之外,那么可以去实现Policy类的一个子类,让其去收集所允许的权限。然后在java.security配置文件中更改下面这行:
policy.provider=sun.security.provider.PolicyFile
在测试期间,我们不喜欢经常地修改标准策略文件。因此,我们更愿意为每一个应用程序配置显式的策略文件,这样将权限写入一个独立的文件(比如MyApp.policy)中即可。要将这个策略文件添加到其他有效的策略中,可以有两个选择。
l 在应用程序的main方法内部设置系统属性:
System.setProperty("java.security.policy", "MyApp.policy");
l 像下面这样启动虚拟机:
Java –Djava.security.policy=MyApp.policy MyApp
对于applet,则可以用如下的启动命令:
appletviewer –J-Djava.security.policy=MyApp.policy MyApp MyApplet.html
可以使用appletviewer的-J选项将任何命令行参数传递给虚拟机。
如果要只是用指定的策略文件,忽略标准策略文件,那么需要在命令行中添加第二个等号:
Java –Djava.security.policy==MyApp.policy MyApp
警告:在测试期间,一个容易犯的错误是在当前用户中留下了一个.java.policy文件,该文件授予了许许多多的权限。如果你发现你的应用程序似乎没有应用策略文件中的规定,就应该检查当前目录下的.java.policy文件。
在默认情况下,Java应用程序是不安装安全管理器的。因此,在安装安全管理器之前,看不到策略文件的作用。有两种方法来安装安全管理器:
l 在main方法中添加下面这行代码:
System.setSecurityManager(new SecurityManager());
l 在启动虚拟机的时候添加命令行选项-Djava.security.manager
java –Djava.security.manager –Djava.security.policy=MyApp.policy MyApp
下面介绍整个策略文件的格式(不包含代码证书部分)。
一个策略文件包含一系列grant项。每一项都具有以下的形式:
grant codesource
{
permission1;
permission2;
…
}
代码来源包含一个代码基(如果某一项适用于所有来源的代码,则代码基可以省略)和值得信赖的用户特征(principal)与证书签名者的名字(如果不要求对该项签名,则可以省略)。
代码基可以设定为:
codebase "url"
如果URL以“/”结束,那么它是一个目录。否则,它将被视为一个JAR文件的名字。该URL总是以“/”作为文件分隔符,即使是Windows中的文件URL。
注意:策略文件阅读器接受两种格式的file URL,即file://localFile和file:localFile。此外,Windows驱动器名前面的斜杠是可有可无的。例如:
file:C:/dir/filename.ext
file:/C:/dir/filename.ext
file://C:/dir/filename.ext
file:///C:/dir/filename.ext
file:C:/dir/filename.ext
权限采用下面的结构:
permission className targetName, actionList;
l className 类名是权限类的全限定类名(比如java.io.FilePermission)。
l targetName目标名是个与权限相关的值,例如,文件权限中的目录名或者文件名,或者是socket权限中的主机和端口。
l actionList 操作列表是一个操作方式的列表,比如read或connect等操作,用逗号分割。
有些权限类并不需要目标名和操作列表。
下表列出了标准的权限和它们执行的操作:
权限 | 目标 | 操作 |
java.io.FilePermission | file 文件 directory 目录 directory/ 目录中的所有文件 * 当前目录中的所有文件 directory/- 目录和其子目录中的所有文件 - 当前目录和其子目录中的所有文件 <<ALL FILES>> 文件系统中的所有文件 | 1. read 读取指定的文件 2. write 对指定的文件进行写操作 3. execute 4. delete 删除指定的文件 |
java.net.SocketPermission | Socket权限的目标由主机和端口范围组成。 (1)主机的描述: hostname或IPaddress 单个主机 localhost或字符串 本地主机 *.domainSuffix 以给定后缀结尾的域中的所有主机 * 所有主机 (2)端口范围的描述: :n 单个端口 :n- 编号大于等于n的所有端口 :-n 编号小于等于n的所有端口 :n1-n2 位于给定范围内的所有端口 | 1. accept 接收一个来自于指定主机和端口号的socket连接 2. connect 打开一个指定主机和端口号的socket连接 3. listen 在指定的本地端口号上等待连接 4. resolve |
java.util.PropertyPermission | property 一个具体的属性 propertyPrefix.* 带有给定前缀的所有属性 | 1. read 访问指定的系统属性 2. write 修改指定的系统属性 |
java.lang.RuntimePermission | createClassLoader 创建一个新的类装载器 getClassLoader setContextClassLoader enableContextClassLoaderOverride createSecurityManager exitVM 应用程序退出 getenv.variableName shutdownHooks setFactory 设置被ServerSocket或Socket使用的socket类或者设置被URL使用的URL流处理器 setIO modifyThread 改变一个线程(例如改变它的优先级,中止它等等) stopThread modifyThreadGroup 改变一个线程组(例如加入一个新的线程,设置守护进程等等) getProtectionDomain readFileDescriptor读取指定的文件 writeFileDescriptor loadLibrary.libraryName 安装一个包含本地方法的动态库 accessClassInPackage.packageName 访问指定的包(被类加载器使用)中的类型 defineClassInPackage.packageName 在指定的包(被类加载器使用)中加入一个新的类 accessDeclaredMembers.className queuePrintJob 初始化一个打印任务请求 getStackTrace setDefaultUncaughtExceptionHandler preferences usePolicy | 无 |
java.awt.AWTPermission | showWindowWithoutWarningBanner accessClipboard accessEventQueue createRobot fullScreenExclusive listenToAllAWTEvents readDisplayPixels replaceKeyboardFocusManager watchMousePointer setWindowAlwaysOnTop setAppletStub | 无 |
java.net.NetPermission | setDefaultAuthenticator specifyStreamHandler requestPasswordAuthentication setProxySelector getProxySelector setCookieHandler getCookieHandler setResponseCache getResponseCache | 无 |
java.lang.reflect.ReflectPermission | suppressAccessChecks | 无 |
java.io.SerializablePermission | enableSubclassImplementation enableSubstitution | 无 |
java.security.SecurityPermission | createAccessControlContext getDomainCombiner getPolicy setPolicy getProperty.keyName setProperty.keyName insertProvider.providerName setProvider. providerName setSystemScope setIdentityPublicKey setIdentityInfo addIdentityCertificate removeIdentityCertificate printIdentity clearProviderProperties.providerName putProviderProperties.providerName removeProviderProperties.providerName getSignerPrivateKey setSignerKeyPair | 无 |
java.security.AllPermission | 无 | 无 |
javax.audio.AudioPermission | 运行记录 | 无 |
javax.security.auth.AuthPermission | doAs doAsPrivileged getSubject getSubjectFromDomainCombiner setReadOnly modifyPrincipals modifyPublicCredentials modifyPrivateCredentials refreshCredential destroyCredentia createLoginContext.contextName getLoginConfiguration setLoginConfiguration refreshLoginConfiguration | 无 |
java.util.logging.LoggingPermission | control | 无 |
java.sql.SQLPermission | setLog | 无 |