Java Security Architecture--Java安全体系技术文档翻译(三)

返回目录

3.2 java.security.CodeSource

本类扩展了HTML中的代码库(CodeBase)的概念,不仅囊括了代码位置(URL)还包含了用于确认从该位置得到的签名代码的公钥证书。注意到这不是一个HTML文件里CodeBase标签的等价物。每一个证书都由一个java.security.cert.Certificate表示,每一个URL都由一个java.net.URL表示。

3.3 java.security.Policy

一个Java应用环境的系统安全规则指定了对于不同来源的代码应该赋予哪些许可,由一个Policy对象代表。更确切的说,它是由一个实现了Policy抽象方法的子类来代表。
为了让一个applet(或者一个运行在SecurityManager之下的应用)被允许执行一些安全动作,例如读或写一个文件,这个applet(或应用)必须被赋予该动作的许可。唯一的例外是代码总是自动拥有其所在目录及其子目录的文件的读许可;它不需要明确的许可就有权限读这些文件。
可以存在很多的Policy对象,虽然在任何时刻都只能有一个“起作用”。当前注册的Policy对象可以通过getPolicy方法来得到,也可以通过setPolicy方法来修改当前注册的Policy(需要由拥有重置Policy权限的代码来执行)。
Policy对象中的规则信息的来源取决于Policy的具体实现。例如规则配置可能被存储为一个ASCII文件,一个序列化的Policy类的二进制文件,或者一个数据库。有一个Policy实现可以通过静态的policy配置文件来获得规则信息。

3.3.1 规则文件的格式

在Policy实现中,规则可以描述在一个或者多个规则配置文件中。规则配置文件指出对于某特定来源的代码应该赋予哪些许可。配置文件必须使用UTF-8编码。
一个规则配置文件包括一个入口记录(entry)的列表。它可以包含一个“keystore”的入口记录,并且包含0个或多个“grant”入口记录。
一个keystore是一个包含私钥及其对应的用来鉴定公钥的数字证书(例如X.509证书链)的数据库。keytool实用工具用来创建并管理keystores。在规则配置文件中指定的keystore用来寻找在该文件的“grant”入口记录中指定的签名者的公钥。如果任何一个grant入口记录指定了签名者别称,或者任何一个grant入口记录指定了一个当事人身份(principal)别称(参照下面),那么一个keystore入口记录必须出现在规则配置文件中。
同时,在规则文件中只能有一个keystore入口记录(第一个之后的其他keystore会被忽略),并且可以出现在规则文件中grant入口记录之外的任何地方。它遵循如下的语法:
keystore "some_keystore_url", "keystore_type";
这里,"some_keystore_url"指定了keystore的URL位置,"keystore_type"指定了keystore的类型。后者是可选的。如果没有指定,就认为keystore类型是由安全属性文档中的属性“keystore.type”指定。
URL是一个基于规则文件位置的相对路径。这样如果安全属性文档中指定规则文件的位置如下:

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

该规则文件有一个入口:
keystore ".keystore";

那么keystore将会从下面地址被加载:
http://foo.bar.com/blah/.keystore

URL也可以是绝对路径。
keystore类型定义了keystore信息的存储和数据格式,以及用来保护保存在该keystore中的私钥和keystore自身的完整性的算法。Sun微系统默认支持的类型是一个名为“JKS”的专有keystore。
规则文档中的每一个“grant”入口记录都由一个代码源(CodeSource)和它的一组许可组成。实际上,一个代码源由一个URL以及一组证书所组成,相应的规则文件一条入口记录中包含了一个URL以及一组签名者的名称。系统在咨询keystore并证实这些签名者的证书后创建相应的代码源。
规则文件中的每一个grant入口记录都拥有下面的格式,开头的“grant”是一个保留字,标志着一个新入口记录的开始,括号内的是可选项。在每一个入口记录内,开头的“permission”是另一个保留字,标志着该入口记录内开始定义一个新许可。每一个grant入口记录赋予一个特定的代码源(CodeSource)及若干当事人身份(principals)以一组许可。

grant [SignedBy "signer_names"] [, CodeBase "URL"]
      [, Principal [principal_class_name] "principal_name"]
      [, Principal [principal_class_name] "principal_name"] ... {
    permission permission_class_name [ "target_name" ] 
                [, "action"] [, SignedBy "signer_names"];
    permission ...
};

逗号前后允许有空格。许可类型的名字必须是全类名,如java.io.FilePermission,不能被简化(如FilePermission)。
注意到动作(action)字段是可选的,所以如果许可类不需要它的话可以被省略。如果提供动作,那它必须紧跟着目标(target)字段。
代码库URL值的确切意思取决于其最后一个字符。一个以“/”结尾的代码库匹配该路径下的所有类文件(不包括JAR文件)。一个以“/*”结尾的代码库匹配该路径下的所有文件(既包括类文件又包括JAR文件)。一个以“/-”结尾的代码库配备该路径及其所有递归子路径下的所有文件(既包括类文件又包括JAR文件)。
代码库字段(URL)是可选的,如果省略,则代表“所有代码库”。
第一次出现的签名者字段是一个字符串别名,该别名通过一个分离的机制导航到一组与该签名者相关的公钥(其证书在keystore里)上。这些公钥用来证实某一签名类确实是被这些签名者所签名的。
该签名者字段可以是一个逗号分隔的包含多个签名者名称的字符串,例如“Adam,Eve,Charles”,意味着被Adam和Eve和Charlest同时签名(就是说,关系是AND不是OR)。
该字段是可选的,如果省略,意味着“任何签名者”,或者换句话说,压根不关心该代码是否被签名。
第二次出现的签名者字段,在一个Permission入口记录内,代表了对该Permission类字节码签名的私钥所对应的公钥保存在keystore中的别名。该许可入口只有在证实了对应的Permission实现类的字节码被别名所代表的签名者正确签名以后才会生效(也就是,会基于本条入口记录授予访问控制许可)。
当事人身份(principal)值由一个 类名/身份名 键值对所描述,该键值对必须存在于当前执行线程的当事人身份集合中。当事人身份集合通过当事人(Subject)对象与正在执行的代码相关联。当事人身份字段是可选的,如果忽略就代表“任何当事人身份”。
KeyStore别名替换的注意事项:
如果当事人身份的 类名/身份名 键值对使用一个引号扩起来的字符串来表示,它会被当作一个keystore别名来处理。通过别名来咨询和查找keystore,从而得到一个X509的证书。如果找到了,那么该当事人身份会自动被作为一个javax.security.auth.x500.X500Principal类型来对待,并且身份名会自动被当作从证书中得到的主题辨识名(subject distinguished name)对待。如果X509证书没有找到,整个grant入口记录会被忽略掉。
CodeBase,SignedBy,和Principal相互之间的次序是不重要的。
一种规则文件格式的非正式的BNF语法如下所示,其中非大写的短语是最终短语,也就是真正规则中的短语。

PolicyFile -> PolicyEntry | PolicyEntry; PolicyFile
PolicyEntry -> grant {PermissionEntry}; |
           grant SignerEntry {PermissionEntry} |
           grant CodebaseEntry {PermissionEntry} |
           grant PrincipalEntry {PermissionEntry} |
           grant SignerEntry, CodebaseEntry {PermissionEntry} |
           grant CodebaseEntry, SignerEntry {PermissionEntry} |
           grant SignerEntry, PrincipalEntry {PermissionEntry} |
           grant PrincipalEntry, SignerEntry {PermissionEntry} |
           grant CodebaseEntry, PrincipalEntry {PermissionEntry} |
           grant PrincipalEntry, CodebaseEntry {PermissionEntry} |
           grant SignerEntry, CodebaseEntry, PrincipalEntry {PermissionEntry} |
           grant CodebaseEntry, SignerEntry, PrincipalEntry {PermissionEntry} |
           grant SignerEntry, PrincipalEntry, CodebaseEntry {PermissionEntry} |
           grant CodebaseEntry, PrincipalEntry, SignerEntry {PermissionEntry} |
           grant PrincipalEntry, CodebaseEntry, SignerEntry {PermissionEntry} |
           grant PrincipalEntry, SignerEntry, CodebaseEntry {PermissionEntry} |
           keystore "url"
SignerEntry -> signedby (a comma-separated list of strings)
CodebaseEntry -> codebase (a string representation of a URL)
PrincipalEntry -> OnePrincipal | OnePrincipal, PrincipalEntry
OnePrincipal -> principal [ principal_class_name ] "principal_name" (a principal)
PermissionEntry -> OnePermission | OnePermission PermissionEntry
OnePermission -> permission permission_class_name
                 [ "target_name" ] [, "action_list"]
                 [, SignerEntry];

现在我们给一些例子。下面的规则给予Roland签名的代码以a.b.Foo的许可:
grant signedBy "Roland" {
    permission a.b.Foo;
}

下面的规则给予所有的代码一个FilePermission(不管是什么签名者或者代码基)
grant {
    permission java.io.FilePermission ".tmp", "read";
};

下面的规则给予由Li和Roland同时签名的代码以两条许可:
grant signedBy "Roland,Li" {
  permission java.io.FilePermission "/tmp/*", "read";
  permission java.util.PropertyPermission "user.*";
};

下面的规则给予Li签名的并且来自源http://java.sun.com的代码以两条许可:
grant codeBase "http://java.sun.com/*", signedBy "Li" {
    permission java.io.FilePermission "/tmp/*", "read";
    permission java.io.SocketPermission "*", "connect";
};

下面的规则对于同时被Li和Roland签名的代码,并且仅当com.abc.TVPermission的字节码是被Li签名的时候,给予他们两条权限:
grant signedBy "Roland,Li" {
  permission java.io.FilePermission "/tmp/*", "read";
  permission com.abc.TVPermission "channel-5", "watch", 
      signedBy "Li";
};

包含第二个签名者字段的原因是当一个许可类尚未在当前Java运行时环境中注册时防止欺骗发生。例如,一份com.abc.TVPermission类的拷贝可以作为一个远程JAR存档的一部分被下载,并且用户安全规则中可能包含了一个关于它的入口记录。由于存档不是长期存活的,于是当第二次com.abc.TVPermission类被下载的时候,可能是从另一个不同的网站,因此确保第二份拷贝是真的就变得至关重要了,既然在用户的安全规则中存在该许可的入口,这很可能反映出了用户对于第一份类字节码拷贝是很信任的。
我们选择使用数字签名的方式来确保真实性,而不是保存第一份拷贝并用它来跟第二分拷贝进行比较的原因是,该许可类的作者可能由于新的设计或代码实现,已经正当的更新了类文件。
请注意:文件路径字符串必须使用平台相关的格式;在统一文件描述语言出现之前这是有必要的。上面的例子展示了在Solaris系统上合适的字符串格式。在Windows系统上,当你直接使用字符串指定一个文件路径时,你需要双反斜杠来代表一个实际上的单反斜杠,例如

grant signedBy "Roland" {
  permission java.io.FilePermission "C:\\users\\Cathy\\*", "read";
};

这是因为字符串会被一个java.io.StreamTokenizer标记器处理,该标记器使用“\”作为一个转义符(例如:“\n”代表换行)因此要求两个反斜杠来表示一个反斜杠。在标记器处理完上述FilePermission的目标字符串,将双反斜杠转换为单反斜杠以后,实际路径的最终结果是
"C:\users\Cathy\*"

最后,这里是一些当事人身份(principal)相关的grant入口记录:
grant principal javax.security.auth.x500.X500Principal "cn=Alice" {
  permission java.io.FilePermission "/home/Alice", "read, write";
};

该规则允许任何以X500Principal, "cn=Alice"身份执行的代码拥有对于“/home/Alice”的读和写的许可。
接下来的例子展示了一个同时包含了代码源和当事人身份信息的grant入口记录。

grant codebase "http://www.games.com",
        signedBy "Duke",
        principal javax.security.auth.x500.X500Principal "cn=Alice" {
    permission java.io.FilePermission "/tmp/games", "read, write";
  };

该规则允许从“www.games.com”下载的,被“Duke”签名的,并被“cn=Alice”身份执行的代码,拥有对于“/tmp/games”目录的读和写许可。
下面的例子展示了一个包含keystore别名替换的grant语句:

keystore "http://foo.bar.com/blah/.keystore";

  grant principal "alice" {
    permission java.io.FilePermission "/tmp/games", "read, write";
  };

“alice”会被替换成javax.security.auth.x500.X500Principal "cn=Alice",假设keystore中与别名“alice”相关的X.509证书有一个主题辨识名“cn=Alice”。该规则允许以X500Principal "cn=Alice"身份执行的代码拥有对“/tmp/games”目录读和写的许可。

3.3.2 规则文件中的属性展开

规则文件(policy files)和安全属性文件(security properties file)是支持属性展开(property expansion)的。
属性展开类似于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";

另外,作为一个特殊情况,如果你在一个代码库中展开一个属性,例如
grant codeBase "file:/${java.home}/lib/ext/"

那么任何文件分隔符将会被自动转换成/,因为代码库是URL格式所以此处需要/。这样一来,在Windows系统上,就算java.home的值是C:\j2sdk1.2,上面的语句也会转换成
grant codeBase "file:/C:/j2sdk1.2/lib/ext/"

这样的话在代码库中你就不需要也不应该使用 ${/}。
规则文件中任何双引号字符串允许的地方都可以使用属性扩展。包括signedby, codebase, target名称, 和action字段。
安全属性文件中的属性"policy.expandProperties"控制着是否允许属性展开。如果该属性值为true(默认值),则允许属性展开。
请注意,你不能使用嵌套属性;他们不会起作用的。例如,

"${user.${foo}}"

不会起作用,即使将user的属性“foo”赋了值“home”也没用。因为属性解析器无法识别嵌套属性;它简单的查找第一个"${",然后就开始查找第一个"}"并尝试将得到的"${user.$foo}"解释为一个属性,由于系统中没有这个属性,所以会失败。
同样注意:如果在一个grant入口记录,permission入口记录,或者keystore入口记录中无法展开一个属性,则该入口记录会被忽略。例如,如果系统没有定义“foo”这个属性,但是你配置了:

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

这样一来,这个grant入口记录中的所有许可都会被忽略。如果你配置了
grant {
  permission Foo "${foo}";
  permission Bar;
};

则仅仅permission Foo "${foo}";这个入口记录会被忽略。最后,如果你配置了
keystore "${foo}";

那么keystore入口记录会被忽略。
最后注意:在Windows系统上,当你直接用字符串指定一个文件路径时,你需要用两个反斜杠来代表一个反斜杠,例如

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

这是因为字符串会被一个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"

3.3.3 规则文件中的一般展开

规则文件也支持一般格式的展开。例如,许可名称可能包含一个如下格式的字符串:
${{protocol:protocol_data}}

如果在一个许可名称中出现了这样一个字符串,则protocol的值决定了要发生的展开的具体类型,protocol_data是用来辅助执行本次展开的。protocol_data可能是空的,在这种情况下上面的字符串应该简单的使用如下格式:
${{protocol}}

默认的规则文件的实现支持两种类型的protocol
1. ${{self}}
self这种协议指定了要使用一个或多个当事人身份的class/name键值对替换${{self}}这个字符串。具体的替换内容取决于该许可所属的grant语句的内容。
如果grant语句不包括任何当事人的信息,那么该许可会被忽略(那些在目标名(target)中包含了${{self}}的许可,只在基于当事人身份上下文的grant语句中才会生效)。例如,在下面的grant语句中BarPermission总是会被忽略:

grant codebase "www.foo.com", signedby "duke" {
    permission BarPermission "... ${{self}} ...";
};

如果grant语句中包含了当事人身份信息,${{self}}会被替换成当事人身份的信息。例如在下面的grant语句中,BarPermission中的${{self}}会被替换成javax.security.auth.x500.X500Principal "cn=Duke":

grant principal javax.security.auth.x500.X500Principal "cn=Duke" {
     permission BarPermission "... ${{self}} ...";
};


如果在grant语句中包含了一个逗号隔开的当事人身份列表,那么${{self}}也会被替换成逗号隔开的当事人身份列表。在当事人类和身份名都使用通配符的情况下,${{self}}会被替换成在当前安全控制上下文快照(AccessControlContext)中的当事人(Subject)所关联的所有身份(Principals)。(也就是通配符计算完成后的当事人身份列表)
下面例子描述了一个同时涉及到self协议和keystore别称替换的场景:

keystore "http://foo.bar.com/blah/.keystore";

grant principal "duke" {
    permission BarPermission "... ${{self}} ...";
};

在上面例子中,“duke”会首先被展开为
javax.security.auth.x500.X500Principal "cn=Duke"

假设keystore中别名“duke”所关联的X.509证书有一个主题辨别名"cn=Duke"。然后,${{self}}会被扩展后的当事人身份替换为:javax.security.auth.x500.X500Principal "cn=Duke"。


2. ${{alias:alias_name}}
alias协议指示了一个java.security.KeyStore别名替换。使用的keystore就是在keystore入口记录中定义的那个。alias_name代表了一个保存在keystore之中的别名。
${{alias:alias_name}}会被替换成javax.security.auth.x500.X500Principal "DN",当DN代表了alias_name所包含的证书的主题辨别名时。例如:

keystore "http://foo.bar.com/blah/.keystore";

grant codebase "www.foo.com" {
      permission BarPermission "... ${{alias:duke}} ...";
};

在上面例子中别名为“duke”的X.509证书从foo.bar.com/blah/.keystore这个keystore中获得。假设duke的证书指定"o=dukeOrg, cn=duke"为其主题辨别名,那么${{alias:duke}}会被替换成javax.security.auth.x500.X500Principal "o=dukeOrg, cn=duke"。
如有如下的错误发生则permission的入口记录会被忽略:
keystore入口没指定
alias_name没有提供
alias_name代表的证书没有获得到
获得的证书不是一个X.509证书

3.3.4 许可的授予

当以某个当事人身份执行一个来自于某代码源的类,安全机制会咨询规则(policy)对象来决定授予其什么样的许可。这是通过调用注册到VM的Policy对象的getPermissions或者implies方法来完成的。
明显的,一个安全域中的给定的代码源可以匹配规则中多个入口记录里的代码源,例如当允许使用通配符“*”的时候。

下面的算法用来在规则中定位合适的许可集合。


  1. 如果代码被签名过,则匹配公钥。
  2. 如果一个公钥无法被规则(规则中定义的keystore)验证,则忽略该公钥。如果所有的公钥都被忽略,则认为该代码没有被签名。
  3. 如果匹配上了公钥,或者没有指定签名者{尝试在规则中为这些公钥匹配所有的URL}
  4. 如果匹配上了公钥(或者没有指定签名者),并且也找到了匹配的URL(或者没有指定代码库codebase){试着将规则中所有的当事人与当前执行线程中的当事人进行匹配}
  5. 如果key,URL,或者当事人中有任一项不匹配,使用内置的默认许可,也就是初始的沙盒许可。


一个规则入口的代码库URL值的确切含义取决于其最后的字符。一个以"/"结尾的代码库匹配指定目录下的所有类文件(不包括JAR文件)。一个以"/*"结尾的代码库匹配指定目录下的所有文件(既包括类文件也包括JAR文件)。一个以"/-"结尾的代码库包括指定目录及其递归子目录下的所有文件(既包括类文件也包括JAR文件)。

举例来说,如果规则中给出"http://java.sun.com/-",那么该网站上的所有代码库都能匹配到这个规则入口。包括"http://java.sun.com/j2se/sdk/"和"http://java.sun.com/people/gong/appl.jar"。
如果多个入口被匹配到,那么这些入口中的所有的许可都会被授予。换句话说,许可授予是可叠加的。例如,如果由A签名的代码可得到许可X,而由B签名的代码可得到许可Y,并且没有指定代码库,那么同时被A和B签名的代码可以得到许可X和许可Y。同样的,如果代码库为"http://java.sun.com/-"的代码可得到许可X,而代码库为"http://java.sun.com/people/*"的代码可得到许可Y,并且没有指定签名者,那么一个从"http://java.sun.com/people/applet.jar"而来的applet就会同时得到许可X和Y。
注意这里对URL的匹配是纯粹语法上的。例如,一个规则可以给出一个指定URL为"ftp://ftp.sun.com"的入口记录。这样的入口记录只有在一个能直接使用ftp获得要执行的代码的时候才是有用的。
文件URL可以被用来指定来自本地文件系统的地址。例如,要指定Solaris系统上的/home/cathy/temp目录下的所有文件,你可以使用

"file:/home/cathy/temp/*"

要指定Windows系统上的C盘的"temp"文件夹下的所有问题,你可以使用
"file:/c:/temp/*"

注意:代码基URL总是使用斜杠(而非反斜杠),不用管他们用在哪个平台上。
你也可以使用一个绝对路径名,例如

"/home/gong/bin/MyWonderfulJava"

3.3.5 默认的系统和用户规则文件

在Policy实现中,规则可以在一个或多个规则配置文件中指定。配置文件指定来自某代码源的代码被授予哪些许可。
一个规则文件可以通过一个简单的文档编辑器来编辑,或者通过一个后面将讲到的图形化规则工具来编辑。
默认存在一个系统范围的规则文件,和一个用户规则文件。
系统规则文件默认存放在

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

这里,java.home是一个系统属性,该属性指定Java 2 SDK安装在哪个目录下。
用户规则文件默认存放在

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

这里,user.home是一个系统属性,该属性指定用户的home目录。
当Policy初始化时,系统规则先被加载,然后再将用户规则添加上去。如果两个规则都不存在,一个内置规则会被使用。内置规则与最初的沙盒规则一样。
规则文件的位置在安全属性文件(security properties file)中指定,安全属性文件的位置是

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

规则文件的位置在具有如下格式的属性值中指定
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

实际上你可以指定很多的URL,包括“http://”格式的,所有指定的规则文件都会被加载。你也可以注释或修改第二条配置以不执行读取默认用户规则文件。
加载的算法是从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=pURL SomeApp

这里,pURL是一个指定规则文件位置的URL,然后这个规则文件就会被加载并添加到在安全属性文件中配置的那些规则文件之后。(参数"-Djava.security.manager"确保默认的安全管理器被注册,这样的话应用就受规则检查的支配,正如在“Applet和应用的安全管理”那一节所描述的。并不要求SomeApp内部注册一个安全管理器。)
如果你使用下面的命令行,其中用了双等号,那么只有该命令行中指定的规则文件会被使用;所有其他规则文件都会被忽略。

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

如果你希望给一个appletviewer传递一个规则文件,同样可以使用一个"-Djava.security.policy"参数,如下所示:
appletviewer -J-Djava.security.policy=pURL  myApplet

注意:假如安全属性文件中属性"policy.allowSystemProperty"的值设置为false(默认是true),那么命令行中的"-Djava.security.policy"将会被忽略(java和appletviewer的命令行都是)。

3.3.6 定制规则计算

当前对于Policy类的设计并没有像它本应该达到的那样适用。我们给予了这个问题很多的思考并在小心谨慎的改进,并在一定程度上确保我们定义的方法对于绝大部分常见的情形都是适用的。同时,也可以提供一个替代规则类来替换掉默认的规则类,只要前者是一个Policy抽象类的子类,并实现了getPermissions方法(如果有必要的话也可重新实现其他方法)。
Policy实现类可以通过重设"policy.provider"(在安全属性文件中定义)的值来改变,将其设置为想要的Policy实现类的全限定名。安全属性文件的位置是

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

这里,{java.home}代表了运行环境安装的目录--要么是Java 2 SDK中jre的目录,要么是Java 2运行时环境的根目录。
属性policy.provider指定了规则类的名字,默认如下:

policy.provider=sun.security.provider.PolicyFile

想定制的话,你可以改变该属性的值来指定另外一个类,如
policy.provider=com.mycom.MyPolicy

注意MyPolicy必须是java.security.Policy的一个子类。或许应该强调一下这种重写规则类的方式只是一种暂时的解决方案,而一个更广泛适用的规则接口将会使这种重写变得没必要。

3.4 java.security.GeneralSecurityException

这是一个继承自java.lang.Exception的新的异常类。提出该异常类的意图是,与安全及安全包相关的异常应该有两种类型。
java.lang.SecurityException和它的子类应该是一个运行时异常(无需检查,不用声明),这些异常很可能导致程序执行的终止。
这种异常都是在某些类型的安全冲突被发现以后抛出。例如,当一些代码企图访问一个文件,但是它没有访问许可时,会抛出这种异常。应用开发者如果想的话,可以捕捉这些异常。
java.security.GeneralSecurityException是一个java.lang.Exception(必须被声明或捕捉)的子类,在安全包中发生的所有其他类型的异常都会抛出该异常。
这种异常是与安全相关的但是并不致命。例如,传入一个无效的密钥很可能并不是一个安全冲突,因此应该被开发者捕捉并处理。

此刻在java.security包中仍然有两个异常继承自RuntimeException。在目前阶段为了向后兼容我们没法修改它们。我们将在未来再返回到这个问题。






===========================================================================

本技术文档的翻译工作由不动明王1984独自完成,特此声明。

翻译辛苦,珍惜劳动,引用时请注明出处!

===========================================================================






返回目录


上一篇:Java Security Architecture--Java安全体系技术文档翻译(二)

下一篇:Java Security Architecture--Java安全体系技术文档翻译(四)


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值