使用Policy文件来设置Java的安全策略 - laiwenqiang的专栏 - CSDN博客

众所周知,Java语言具有完善的安全框架,从编程语言,编译器、解释程序到Java虚拟机,都能确保Java系统不被无效的代码或敌对的编译器暗中破坏,基本上,它们保证了Java代码按预定的规则运作。但是,当我们需要逾越这些限制时,例如,读写文件,监听和读写Socket,退出Java系统等,就必须使用数字签名或安全策略文件(*.Policy)。

在企业内部网中,本文提出了使用安全策略文件来设置java程序权限的一种简单的方法。由于企业内部网中各台计算机的位置、用途和安全性明确,更适于使用安全策略文件来设置java的权限,软件的安装、设置、升级和迁移都非常的方便,并且,还可以和数字签名配合使用,更重要的是,可以细分每个java程序的权限,使用起来灵活方便。

Java中安全策略的概念

Java应用程序环境的安全策略,详细说明了对于不同的代码所拥有的不同资源的许可,它由一个Policy对象来表达。为了让applet(或者运行在SecurityManager下的一个应用程序)能够执行受保护的行为,例如读写文件,applet(或Java应用程序)必须获得那项操作的许可,安全策略文件就是用来实现这些许可。

Policy对象可能有多个实体,虽然任何时候只能有一个起作用。当前安装的Policy对象,在程序中可以通过调用getPolicy方法得到,也可以通过调用setPolicy方法改变。Policy对象评估整个策略,返回一个适当的Permissions对象,详细说明那些代码可以访问那些资源。

策略文件可以储存在无格式的ASCII文件,或Policy类的二进制文件,或数据库中。本文仅讨论无格式的ASCII文件的形式。

Policy文件的格式

为了能够更好地理解下面的内容,建议在阅读时参照\jdk1.2\jre\lib\security\java.policy文件和\jdk1.2\jre\lib\security\java.security文件的内容。

Policy文件的语法格式与说明

一个Policy文件实质上是一个记录列表,它可能含有一个“keystore”记录,以及含有零个或多个“grant”记录。其格式如下:

keystore "some_keystore_url", 
"keystore_type";
grant [SignedBy "signer_names"] 
[, CodeBase "URL"] {
Permission permission_class_name 
[ "target_name" ] 
[, "action"] [, SignedBy "signer_names"];
Permission ...
};

keystore记录

  • 一个keystore是一个私有密钥(private keys)数据库和相应的数字签名,例如X.509证书。Policy文件中可能只有一条keystore记录(也可能不含有该记录),它可以出现在文件中grant记录以外的任何地方。Policy配置文件中指定的keystores用于寻找grant记录中指定的、签名者的公共密钥(public keys),如果任何grant记录指定签名者(signer_names),那么,keystore记录必须出现在policy配置文件中。
  • “some_keystore_url”是指keystore的URL位置,”keystore_type”是指keystore的类型。第二个选项是可选项,如果没有指定,该类型则假定由安全属性文件(java.security)中的”keystore.type”属性来确定。keystore类型定义了keystore信息的存储和数据格式,用于保护keystore中的私有密钥和keystore完整性的算法。Sun Microsystems支持的缺省类型为“JKS”。

grant记录

  • 在Policy文件中的每一个grant记录含有一个CodeSource(一个指定的代码)及其permission(许可)。
  • Policy文件中的每一条grant记录遵循下面的格式,以保留字“grant”开头,表示一条新的记录的开始,“Permission”是另一个保留字,在记录中用来标记一个新的许可的开始。每一个grant记录授予一个指定的代码(CodeBase)一套许可(Permissions)。
  • permission_class_name必须是一个合格并存在的类名,例如java.io.FilePermission,不能使用缩写(例如,FilePermission)。
  • target_name用来指定目标类的位置,action用于指定目标类拥有的权限。
  • target_name可以直接指定类名(可以是绝对或相对路径),目录名,也可以是下面的通配符:
    directory/* 目录下的所有文件
    *当前目录的所有文件
    directory/-目录下的所有文件,包括子目录
  • 当前目录下的所有文件,包括子目录
    《ALL FILES》文件系统中的所有文件
    对于java.io.FilePermission,action可以是:
    read, write, delete和execute。
    对于java.net.SocketPermission,action可以是:
    listen,accept,connect,read,write。

Policy文件中的属性扩展(Property Expansion)

属性扩展与shell中使用的变量扩展类似,它的格式为:

${some.property}

实际使用的例子为:

permission java.io.FilePermission 
"${user.home}", "read";
"${user.home}"的值为"d:\Project",

因此,下面的语句和上面的语句是一样的:

permission java.io.FilePermission
d:\Project ", "read";

实例

当初始化Policy时,首先装载系统Policy,然后再增加用户Policy,如果两者都不存在,则使用缺省的Policy,即原始的沙箱模型。

系统Policy文件的缺省位置为:

{java.home}/lib/security/java.policy (Solaris)
{java.home}\lib\security\java.policy (Windows)
用户Policy文件的缺省位置为:
{user.home}/.java.policy (Solaris)
{user.home}\.java.policy (Windows)

其实,在实际使用中,我们可能不会象上面介绍的那么复杂,特别是在不使用数字签名时。这时,我们完全可以借鉴JDK 1.2提供给我们的现成的\jdk1.2\jre\lib\security\java.policy文件,根据我们的需要作相应的修改,本文就针对不使用数字签名情况详细说明安全策略文件的用法。
下面,是一个完整的在Windows 95/98/NT下使用的.java.policy文件。在文件中,分别使用注释的形式说明了每个“permission”记录的用途。

// For LanServerTalk.java and LanClientTalk.java

grant { 
//对系统和用户目录“读”的权限
permission java.util.PropertyPermission
"user.dir", "read";
permission java.util.PropertyPermission 
"user.home", "read";
permission java.util.PropertyPermission 
"java.home", "read";
permission java.util.PropertyPermission 
"java.class.path", "read";
permission java.util.PropertyPermission 
"user.name", "read"; 

//对线程和线程组的操作权限
permission java.lang.RuntimePermission
"modifyThread";
permission java.lang.RuntimePermission
"modifyThreadGroup";

//操作Socket端口的各种权限
permission java.net.SocketPermission
"-", "listen";
permission java.net.SocketPermission
"-", "accept";
permission java.net.SocketPermission 
"-", "connect";
permission java.net.SocketPermission "-", "read";
permission java.net.SocketPermission "-", "write";

//读写文件的权限
permission java.io.FilePermission "-", "read";
permission java.io.FilePermission "-", "write";

//退出系统的权限,例如System.exit(0)
permission java.lang.RuntimePermission "exitVM";
};

java.policy文件的使用

对于windows 95/98/NT,使用.java.policy文件的方法主要有下面两种。

使用缺省目录

我们可以简单地将编辑好的.java.policy文件拷贝到windows 95/98/NT的HOME目录,这时,所有的applet(或Java应用程序)可能都拥有某些相同的权限,使用起来简单,但不灵活(例如:对于java.io.FilePermission ,其目标类的target_name必须使用绝对路径),如果不是在企业内部网中使用,还可能存在一定安全隐患。

在命令行中指定

在命令行,如果我们希望传递一个Policy文件给appletviewer,还可以使用”-J-Djava.security.policy”来指定policy的位置:

appletviewer -J-Djava.security.
policy=pURL myApplet

pURL为Policy文件的位置。下面,是一个实际的例子,以当前目录的.java.policy文件所指定的安全策略运行当前目录的LanServerTalk.html(文件中装载并运行LanServerTalk.java):

appletviewer -J-Djava.security.policy
=.java.policy LanServerTalk.html 

这种方法使用灵活,特别是作为一个软件包在企业内部网中发布时,安装、设置和迁移软件,基本无须修改Policy文件的内容,使用起来相当简单,而且,安全许可的范围控制较精细。

    • *

缺省策略实现和策略文件语法

上次修改时间: 1998 年 10 月 30 日

Java 应用程序环境的策略(对不同来源的代码指定权限)由 Policy 对象来表示。更明确地说,就是由 Policy 类(包含在 java.security 包中)的实现抽象方法的 Policy 子类来表示。

Policy 对象所用策略信息的源位置由 Policy 实现决定。缺省 Policy 实现从静态策略配置文件获得自己的信息。本文档的其余部分叙述了缺省 Policy 实现及其所读取的策略文件中必须使用的语法。有关使用 Policy Tool 来创建策略文件(不必知道所需语法)的详细信息,请参阅《策略工具文档》 (for Solaris) (for Windows)。

以下是本文档其余部分的概要:

  • 缺省 Policy 实现
  • 缺省策略文件位置
  • 更改 Policy 实现
  • 策略文件语法
  • 策略文件示例
  • 策略文件中的属性扩展

缺省 Policy 实现

在缺省 Policy 实现中,可在一个或多个策略配置文件中指定策略。配置文件的作用是指定特定代码源的代码所能获得的权限。

可利用简单的文本编辑器或 Policy Tool 实用程序来编写策略文件。

缺省情况下,系统上只有单个全系统策略文件和唯一的(可选)用户策略文件。

首次调用缺省 Policy 对象的 getPermissions 方法或在任何时候调用 Policy 对象 refresh 方法时,即对其进行初始化。初始化包括分析策略配置文件(请参阅策略文件语法)及组装 Policy 对象。

缺省策略文件位置

如前所述,系统在缺省情况下具有单个全系统策略文件和唯一的用户策略文件。

系统策略文件的缺省位置为:

java.home/lib/security/java.policy  (Solaris)
java.home\lib\security\java.policy  (Windows)

注意: java.home 指的是名为“java.home”的系统属性的值,它指定 JDK 的安装目录。

系统策略文件可用于授予全系统代码权限。与 JDK 一起安装的 java.policy 文件可向标准扩展 (Java standard extensions) 授予全部权限,允许任何用户在无特权要求的端口进行监听,同时允许任何代码读取某些对安全不敏感的“标准”属性(例如“os.name”和“file.separator”属性)。

用户策略文件的缺省位置为

user.home/.java.policy  (Solaris)
user.home\.java.policy  (Windows)

注意: user.home 指的是名为“user.home”的系统属性的值,它指定用户的主目录。
在 Windows 系统中,假定用户名是 uName,“user.home”属性的缺省值为:

C:\Winnt\Profiles\uName(多用户 Windows NT 系统中)
C:\Windows\Profiles\uName(多用户 Windows 95 系统中)
C:\Windows(单用户 Windows 95 系统中)

初始化 Policy 时,将首先加载系统策略,然后在 Policy 中添加用户策略。如果两种策略均不存在,则采用内置策略。该内置策略与原始的沙箱策略相同。

策略文件的位置在安全属性文件中指定。安全属性文件的位置为:

java.home/lib/security/java.security  (Solaris)
java.home\lib\security\java.security  (Windows)

如上所述,java.home 指示 JDK 的安装目录。策略文件的位置被指定为其名称具有以下形式的属性的值:

policy.url.n

其中 n 为数字。应采用以下形式的语句行来指定每个属性值:

policy.url.n=URL

其中,URL 为 URL 规范。

例如,安全属性文件中将把缺省系统和用户策略文件定义为:

policy.url.1=file:${java.home}/lib/security/java.policy
policy.url.2=file:${user.home}/.java.policy

有关利用特殊语法(例如利用 ${java.home} 来指定 java.home 属性值)来指定属性值的详细信息,请参阅属性扩展。

实际上,用户可以指定多个 URL(包括“http://”形式的 URL),从而加载所有指定的策略文件。也可注释掉或更改第二个 URL,从而禁止读取缺省用户策略文件。

该算法自 policy.url.1 开始,然后不断递增直到查不到 URL 为止。因此,如果有了 policy.url.1 和 policy.url.3,就不会读取 policy.url.3。

运行时指定其它策略文件

在执行应用程序时也可以指定附加的或不同的策略文件,方法是用“-Djava.security.policy”命令行参数来指定(该命令行参数设置 java.security.policy 属性值)。例如,如果使用

java -Djava.security.manager -Djava.security.policy=someURL SomeApp

这里 someURL 是指定策略文件位置的 URL,则除了加载安全属性文件中指定的所有策略文件外,还会加载本方法所指定的策略文件。

注意:

URL 可以是任何标准 URL,也可以只是当前目录下策略文件的文件名,如下例所示:

java -Djava.security.manager -Djava.security.policy=mypolicy WriteFile

“-Djava.security.manager”参数可确保缺省安全管理器已被安装,这样就容易对应用程序进行策略检查。如果应用程序 SomeApp 安装有安全管理器,则不需要该参数。
如果使用

java -Djava.security.manager -Djava.security.policy==someURL SomeApp

(请注意双等号),就会仅使用指定的策略文件,而安全属性文件中指出的策略文件将被忽略。

如果要将策略文件传递给 appletviewer,就应使用参数“-J-Djava.security.policy”,如下所示:

appletviewer -J-Djava.security.policy=someURL myApplet

请注意:如果将安全属性文件中的“policy.allowSystemProperty”属性设置为“false”,就会忽略“-Djava.security.policy”策略文件值(对于 java 和 appletviewer 命令)。缺省值为“true”。

更改 Policy 实现
可以用其它 policy 类来代替缺省 Policy 实现类,前提是前者属于抽象 Policy 类的子类并可实现 getPermissions 方法(及其它必要的方法)。

缺省 Policy 实现的更改可通过编辑安全属性文件来完成,其中安全属性文件指 JDK lib/security 目录中的 java.security 文件。

下面给出一种可在 java.security 中设置的属性类型的形式:

policy.provider=PolicyClassName

PolicyClassName 必须指定所需 Policy 实现类的完整名称。该属性的缺省安全属性文件项如下所示:

policy.provider=sun.security.provider.PolicyFile

要想自定义安全属性文件项,可通过更改属性值来指定另一个类,如下例所示:

policy.provider=com.mycom.MyPolicy

策略文件语法

JDK 的策略配置文件可用于指定来自特定代码源的代码所能获得的权限(何种系统资源访问类型)。

为了使 applet(或在安全管理器下运行的应用程序)能够执行受保护的动作(例如读写文件),必须向 applet(或应用程序)授予进行该动作的权限。在缺省 Policy 实现中,必须由策略配置文件中的 grant 项授予该权限。有关详细信息,请参阅以下内容及 “Java 安全体系结构规范”(唯一的例外是:代码对位于与它自身同一 (URL) 位置并且对那一位置子目录下的文件总是自动拥有读权限,而无需授予明确的权限)。

策略配置文件主要包含授权项列表。其中可能包含“keystore”(密钥仓库)项及零个或多个“grant”(授权)项。

Keystore 项

keystore 是存放私钥及相关数字证书(例如验证对应的公钥的 X.509 证书链)的数据库。keytool 实用程序 (for Solaris) (for Windows) 用于创建和管理密钥仓库。策略配置文件中所指定的 keystore 用于查找在该文件的授权项中所指定的签名人公钥。如果某一授权项指定了签名人别名(请参阅以下内容),则在策略配置文件中必须含有 keystore 项。

目前,在策略文件中只能有一个 keystore 项(第一项后的其它 keystore 项将被忽略),且该项可位于文件授权项以外的任何位置。其语法如下所示:

keystore "some_keystore_url", "keystore_type";

其中“some_keystore_url”指定密钥仓库的 URL 位置,而“keystore_type”指定密钥仓库的类型。

URL 是相对于策略文件位置而言。因此,如果在安全属性文件中按以下方式指定策略文件:

policy.url.1=http://foo.bar.com/fum/some.policy

而且策略文件中含有以下项:

keystore ".keystore";

就会从下列位置加载密钥仓库:

http://foo.bar.com/fum/.keystore

URL 也可以是绝对 URL。

keystore type 定义密钥仓库信息的存储和数据格式,同时也定义用于保护密钥仓库中私钥及密钥仓库自身完整性的算法。Sun Microsystems 所支持的缺省类型是名为“JKS”的专用密钥仓库类型。因此,如果密钥仓库类型属于“JKS”,就无需在 keystore 项中加以指定。

授权项

通常认为执行代码来自于某“代码源”(由 CodeSource 类型的对象表示)。代码源不仅包含代码的源位置 (URL),而且还包括对包含与签写代码的私钥相对应的公钥的证书之引用。代码源中的证书通过用户密钥仓库中的符号别名引用。

每个授权项包括一个或多个“权限项”,前面为可选 codeBase 和 signedBy 名字/值对,用于指定要授予权限的代码。授权项的基本格式如下所示:

grant signedBy "signer_names", codeBase "URL" {
permission permission_class_name "target_name", "action",
   signedBy "signer_names";
....
permission permission_class_name "target_name", "action",
   signedBy "signer_names";
};

以上所有非斜体的项必须按原样出现(尽管大小写无关紧要且部分为可选项,如下所示)。 斜体项代表变量值。

授权项必须以 grant 开头。

SignedBy 和 CodeBase 域

signedBy 和 codeBase 名字/值对为可选域,其间的顺序无关紧要。

signedBy 值表示存储在密钥仓库中的证书别名。该证书内的公钥用于验证代码上的数字签名;用户可以向由私钥(私钥对应于该别名所指定的 keystore 项中的公钥)签名的代码授予权限。

signedBy 的值可以是由逗号分隔的多个别名。 例如“Adam,Eve,Charles”,其含义为“Adam,Eve 和 Charles 签名”;它们之间的关系是 AND(与)而非 OR(或)。更确切地说,“Adam 签名的代码”语句的含义是“JAR 文件中有含类文件的代码,这个 JAR 文件已用密钥仓库中别名为 Adam 的项中与公钥所对应的私钥签名”。

signedBy 域可选,这是因为如果省略该域,则表示“任何签名人”。代码是否有签名或由谁签名都没有关系。

codeBase 值表示的是代码源位置;用户可向来自该位置的代码授权。空 codeBase 项表示“任何代码”;代码来源于何处没有关系。

注意: codeBase 值是 URL,因此应该始终用正斜杠(而不要用反斜杠)作为目录分隔符,即使代码源实际在 Windows 系统上。这样,如果 Windows 系统上代码的源位置实际上是 C:\somepath\api\,则 codeBase 策略项的外观将如下所示:

grant codeBase "file:/C:/somepath/api/" {
  ...
}

codeBase

值的准确含义要取决于最后的字符。后面跟着“/”的 codeBase 将匹配指定目录下的所有类文件(非 JAR 文件)。后面跟着“/*”的 codeBase 将匹配该目录下的所有文件(类文件和 JAR 文件)。后面跟着“/-”的 codeBase 将匹配该目录下的所有文件(类文件和 JAR 文件)及该目录下子目录中的所有文件。下表说明了各种不同的情况。

下载代码的 Codebase URL

策略中的 Codebase URL

是否匹配?

java.sun.com/people/gong/

java.sun.com/people/gong

java.sun.com/people/gong/

java.sun.com/people/gong/

java.sun.com/people/gong/

java.sun.com/people/gong/*

java.sun.com/people/gong/

java.sun.com/people/gong/-

java.sun.com/people/gong/appl.jar

java.sun.com/people/gong/

java.sun.com/people/gong/appl.jar

java.sun.com/people/gong/-

java.sun.com/people/gong/appl.jar

java.sun.com/people/gong/*

java.sun.com/people/gong/appl.jar

java.sun.com/people/-

java.sun.com/people/gong/appl.jar

java.sun.com/people/*

java.sun.com/people/gong/

java.sun.com/people/-

java.sun.com/people/gong/

java.sun.com/people/*

权限项

权限项必须以 permission 开头。上述模板中的字 permission_class_name 的实际值可以是特定的权限类型(例如 java.io.FilePermission 或 java.lang.RuntimePermission)。

“action” 对于许多权限类型而言都是必需的,例如 java.io.FilePermission(指定允许何种类型的文件访问权限)。 对于诸如 java.lang.RuntimePermission 等权限类型则为可选项:既可以在 permission_class_name 之后的 “target_name” 值中指定权限,也可以不指定权限。

权限项的 signedBy 名字/值对为可选项。如果有名字/值对,则表示为已签名权限。意即必须由给定的别名对权限类签名,方可授予权限。例如,假定有以下授权项:

grant {
     permission Foo "foobar", signedBy "FooSoft";
}

如果将 Foo.class 权限放到 JAR 文件中,且该 JAR 文件已由与 “FooSoft” 别名所指定的证书中的公钥相对应的私钥签名,或在 Foo.class 是系统类(因为系统类不受策略限制)的情况下,即可授予 Foo 权限类型。

权限项中出现的项目必须按指定顺序出现(permission,permission_class_name,”target_name”,”action” 和 signedBy “signer_names”)。分号表示项终止。

大小写对于标识符(permission、signedBy、codeBase 等)来说并不重要,但对于 permission_class_name 或作为值传递过来的字符串而言就很重要了。

有关 Windows 系统上文件路径规范的注意事项

请注意:在指定 java.io.FilePermission 时,”target_name” 是文件路径。在 Windows 系统上,无论何时在字符串中(而不是在 codeBase URL 中)直接指定文件路径,路径中都需要两个反斜杠来代表一个实际的反斜杠,如下例所示:

grant {
  permission java.io.FilePermission "C:\\users\\cathy\\foo.bat", "read";
};

原因在于:字符串是由符号处理器 (java.io.StreamTokenizer) 来处理的。符号处理器允许将“\”用作转义字符串(例如,“\n”表示换行),因此需要用两个反斜杠来表示一个反斜杠。符号处理器处理完以上文件路径字符串后,将把双反斜杠转换成单个反斜杠,其最终结果为:

"C:\users\cathy\foo.bat"

策略文件示例

策略配置文件中两项的示例如下所示:

// 如果代码由 “Duke” 签字,则向 /tmp 中的所有文件
// 授予读/写访问权限:

grant signedBy "Duke" {
   permission java.io.FilePermission "/tmp/*", "read,write";
};

// 授予所有用户以下权限:

grant { permission java.util.PropertyPermission "java.vendor"; };

另一个示例策略配置文件如下所示。

grant signedBy "sysadmin", codeBase "file:/home/sysadmin/*" {
  permission java.security.SecurityPermission "Security.insertProvider.*";
  permission java.security.SecurityPermission "Security.removeProvider.*";
  permission java.security.SecurityPermission "Security.setProperty.*";
};

本示例规定:只有满足以下条件的代码才能调用 Security 类中的方法以添加或删除提供者或者设置 Security 属性:

代码将从位于本地文件系统上“/home/sysadmin/”目录下的签名 JAR 文件中加载。
可以用密钥仓库中别名“sysadmin”所引用的公钥来校验签名。
可以忽略代码源中两个组件的任何一个(或两者)。下面是忽略 codeBase 的示例:

grant signedBy "sysadmin" {
  permission java.security.SecurityPermission "Security.insertProvider.*";
  permission java.security.SecurityPermission "Security.removeProvider.*";
};

如果该策略生效,则来自 JAR 文件(由 “sysadmin” 签名)的代码可以添加/删除提供者,而不管 JAR 文件来源于何处。

下面是没有签名人的示例:

grant codeBase "file:/home/sysadmin/-" {
  permission java.security.SecurityPermission "Security.insertProvider.*";
  permission java.security.SecurityPermission "Security.removeProvider.*";
};

这里,来自本地文件系统“/home/sysadmin/”目录下任意位置的代码都可以添加/删除提供者。 该代码不必签名。

下面是既不含 codeBase 也不含 signedBy 的示例:

grant {
  permission java.security.SecurityPermission "Security.insertProvider.*";
  permission java.security.SecurityPermission "Security.removeProvider.*";
};

此处,由于两个代码源组件均被忽略,因此任何代码(不管来自于何处,是否已签名或由何人签名)都可添加/删除提供者。

策略文件中的属性扩展

策略文件和安全属性文件中可以进行属性扩展。

属性扩展类似于扩展 shell 中的变量。也就是说,当类似

${some.property}

的字符串出现在策略文件或安全属性文件中时,它将被扩展为系统属性的值。 例如,

permission java.io.FilePermission "${user.home}", "read";

将把 “${user.home}” 扩展为使用 “user.home” 系统属性的值。如果该属性的值是 “/home/cathy”,则以上示例等价于:

permission java.io.FilePermission "/home/cathy", "read";

为了能在与平台无关的策略文件中使用,也可采用特殊记号 “/"。该记号是"/"。该记号是"{file.separator}” 的简化表示。这种方式允许使用下列字符串:

permission java.io.FilePermission "${user.home}${/}*", "read";

如果 “user.home” 属性的值是 /home/cathy,而且是在 Solaris 系统上,则以上字符串将转换为:

permission java.io.FilePermission "/home/cathy/*", "read";

如果 “user.home” 值是 C:\users\cathy,而且是在 Windows 系统上,则以上字符串将转换为:

permission java.io.FilePermission "C:\users\cathy\*", "read";

同样,作为一种特例,如果扩展 codebase 中的属性,例如

grant codeBase "file:${java.home}/lib/ext/"

则任何文件分隔符都将自动转换为“/”。这样,在 Windows 系统上,以上字符串将转换为:

grant codeBase "file:C:/jdk1.2/lib/ext/"

即使 “java.home” 被设置为 C:\jdk1.2。因此,用户就不必也不应该在 codeBase 字符串中使用 ${/}。

策略文件中允许使用双引号字符串的地方都可进行属性扩展。其中包括 “signer_names”、”URL”、”target_name” 和 “action” 域。

是否允许属性扩展由安全属性文件中的“policy.expandProperties”属性控制。如果该属性为真(缺省值),则允许扩展。

请注意:不能使用嵌套属性;嵌套属性将无效。 例如,

"${user.${foo}}"

是无效的,即使将“foo”属性设置为“home”。原因在于属性解析程序不能识别嵌套属性;解析程序只是简单地搜索第一个“”,然后继续搜索直到找到第一个“”为止,同时试图将搜索结果(这里是"”,然后继续搜索直到找到第一个“”为止,同时试图将搜索结果(这里是"{user.$foo}”)解释为属性。如果没有这种属性,则解析程序就会发生解释失败。

也请注意:如果在 grant 项、permission 项或 keystore 项中无法扩展某个属性,则该项将被忽略。例如,如果在没有定义系统属性“foo”的情况下使用语句:

grant codeBase "${foo}" {
  permission ...;
  permission ...;
};

则该 grant 项中的所有权限都将被忽略。如果使用语句:

grant {
  permission Foo "${foo}";
  permission Bar;
};

则将仅忽略“permission Foo…”项。最后,如果使用语句:

keystore "${foo}";

则将忽略 keystore 项。

Windows 系统、文件路径和属性的扩展

如上所述,在 Windows 系统上,当直接在字符串中(而不是在 codeBase URL 中)指定文件路径时,用户需要用两个反斜杠来代表文件路径中一个实际的反斜杠,如下例所示:

grant {
    permission java.io.FilePermission "C:\\users\\cathy\\foo.bat", "read";
};

原因在于:字符串是由符号处理器 (java.io.StreamTokenizer) 来处理的。符号处理器允许将“\”用作转义字符串(例如,“\n”表示换行),因此需要用两个反斜杠来表示一个反斜杠。符号处理器处理完以上文件路径字符串后,将把双反斜杠转换成单个反斜杠,其最终结果为:

"C:\users\cathy\foo.bat"

符号处理器处理完字符串后,即进行字符串中的属性扩展。因此,如果使用字符串:

"${user.home}\\foo.bat"

则符号处理器首先处理字符串,即将双反斜杠转换成单个反斜杠,其结果为:

"${user.home}\foo.bat"

随即扩展 ${user.home} 属性,其最终结果为:

"C:\users\cathy\foo.bat"

以上假定 “user.home” 的值是 C:\users\cathy。当然,为实现与平台无关,最好在开始指定字符串时不要显式带上斜杠,即可以用 ${/} 属性来代替,如下例所示:

"${user.home}${/}foo.bat
使用Policy文件来设置Java的安全策略整理而来

Original url: Access
Created at: 2019-04-24 18:29:39
Category: default
Tags: none

请先后发表评论
  • 最新评论
  • 总共0条评论