java 安全管理器详解(1)

一、权限控制的最小单元java.security.Permission

可以把Permission理解为java安全的最小单元,是权限的抽象代表。通常一个Permission子类构造器会有两个参数,一个是目标的名称(对谁进行权限控制);另外一个是对目标允许的操作(例如对一个文件读操作)。

Permission是一个抽象类,包含的方法如下:

abstract boolean equals(Object obj);
abstract String getActions(); 
abstract boolean implies(Permission permission);
PermissionCollection newPermissionCollection();

以其子类FilePermission(表示对文件权限)为例子,来说明具体的用法:
构造函数如下:

FilePermission(String path, String actions);

第一个参数即为权限控制的具体目标(path是文件或者目录的路径名);第二个参数即为对文件的操作,多个操作用逗号分隔,允许的操作包括:

READ、WRITE、EXECUTE、DELETE

对D盘demo.txt文件允许的操作为读和删除,具体写法可为:

FilePermission fp = new FilePermission("D:/demo.txt","read,delete");


我们现在明白了,Permission用来描述一个具体的权限,那么接下来就有问题了,谁将拥有这个权限?

具体来说,我们定义好了一个权限,如:“对D盘demo.txt文件允许的操作为读和删除” 那么我们如何将这个权限授予一段代码?

二、如何将定义好的一个或多个权限授予一段代码(类)

首先来了解几个概念

1.保护域(protection domain)

意如其名,一块区域。即使是一块区域,那么一定有一些东西属于这个区域,一定有一些东西属性那个区域。
那么放在代码的世界中,也是说有一些代码(类)属于这块保护区,一些代码(类)属于另外一块保护区。

java可以对不同的保护区授予不同的权限,那么这块区域中的代码(类)就会拥有所在保护区的权限。

API的具体体现为:java.security.ProtectionDomain

2.代码源(CodeSource)

一定要能惟一地标识一段代码(类)以保证它的访问权限没有冲突。惟一标识属性共有两项:代码的来源(代码装载到内存所用的 URL)和代码的 signer 实体(由对应于运行代码的数字签名的一组公共密钥指定)

我们知道标识一个类在Java中的唯一性是根据:加载它的类加载器和该类本身


三、权限与保护域的具体实现

在java中,以类为单位,将不同的类分在不同的保护域。每个类加载器具有一个保护域,使用同一个类加载器加载的类在同一个保护域,也就是说具有相同的权限。

阅读java.security.ProtectionDomain源码,也能发现这个特征。ProtectionDomain类具有classloader属性:

/* ClassLoader the protection domain was consed from */
private ClassLoader classloader ;

同样ProtectionDomain类也包括该区域被授予的权限:

/* the rights this protection domain is granted */
private PermissionCollection permissions ;

下面跟着我来阅读类加载器(java.lang.ClassLoader)的部分源码:

默认保护域:

// The "default" domain. Set as the default ProtectionDomain on newly
// created classes.
private final ProtectionDomain defaultDomain =
    new ProtectionDomain(new CodeSource( null, (Certificate[]) null ),null , this , null);

new ProtectionDomain的第二个参数代表授予的权限集合,默认值为null。

类加载方法:

protected final Class <?> defineClass(String name , byte[] b , int off , int len,
                                     ProtectionDomain protectionDomain )
    throws ClassFormatError
{
    protectionDomain = preDefineClass(name , protectionDomain );

    Class c = null;
    String source = defineClassSourceLocation(protectionDomain );

    try {
        //本地方法加载类
        c = defineClass1( name, b, off, len, protectionDomain , source );
    } catch (ClassFormatError cfe ) {
        c = defineTransformedClass( name, b, off, len, protectionDomain , cfe ,
                                   source);
    }

    postDefineClass( c, protectionDomain );
    return c ;
}


private ProtectionDomain preDefineClass(String name,ProtectionDomain pd )
{
    if (!checkName(name ))
        throw new NoClassDefFoundError( "IllegalName: " + name);

    if ((name != null) && name.startsWith( "java." )) {
        throw new SecurityException
            ( "Prohibited package name: " +
             name.substring(0, name .lastIndexOf('.' )));
    }
    if (pd == null) {
        pd = defaultDomain ;
    }

    if (name != null) checkCerts( name, pd .getCodeSource());

    return pd ;
}

该方法的第五个参数为保护域,也就是说在手动加载类时可以自定义保护域。如果该参数为null,则使用默认保护域。

现在已经规定了不同类拥有不同的权限,那么由谁来监督类有没有越权呢?

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值