一个例子理解AccessController.doPrivileged()


示例中需要在eclipse中创建2个project:ServiceCentre和TestService

java.policy

grant codeBase  " file:/D:/Workspaces/ExchangeConnect_V2_Trunk_Maven_workspace/ServiceCentre/bin/* "   {
    permission java.io.FilePermission 
"c:/TestService-1.0.jar""read";
    permission java.lang.RuntimePermission 
"createClassLoader";
}
;

grant codeBase 
" file:/c:/TestService-1.0.jar "   {
    permission java.io.FilePermission 
"C:/text.txt""read";
}
;




Project - ServiceCentre

package  test;

import  java.lang.reflect.Method;
import  java.net.URL;
import  java.net.URLClassLoader;

/**
 * 
@author Donf Yang
 
*/

public   class  ServiceCentreMain  {

    
public void loadService() {
        URL[] urls;
        
try {
            urls 
= new URL[] new URL("file:c:/TestService-1.0.jar") };
            URLClassLoader ll 
= new URLClassLoader(urls);
            
final Class a = ll.loadClass("test.TestService");
            Object o 
= a.newInstance();
            Method m 
= a.getMethod("doService"null);
            m.invoke(o, 
null);

        }
 catch (Exception e) {
            e.printStackTrace();
        }

    }


    
/**
     * 
@param args
     
*/

    
public static void main(String[] args) {
        ServiceCentreMain s 
= new ServiceCentreMain();
        s.loadService();
    }


}


 

Project - TestService
将TestService打包,放到C盘
package  test;

import  java.io.FilePermission;
import  java.security.AccessController;
import  java.security.Permission;

/**
 * 
@author Donf Yang
 * 
 
*/

public   class  TestService  {

    
public void doService() {
        
        doFileOperation();

    }


    
private void doFileOperation() {
        Permission perm 
= new FilePermission("C:/text.txt""read");
        AccessController.checkPermission(perm);
        System.out.println(
"TestService has permission");
    }


}

运行这个例子的时候,会出现权限错误,把doService()修改一下,就可以顺利通过
public   void  doService()  {

        
// doFileOperation();

        AccessController.doPrivileged(
new PrivilegedAction() {
            
public Object run() {
                doFileOperation();
                
return null;
            }

        }
);
    }

在这个例子中AccessControlContext的stack顺序为
2.  file:/D:/Workspaces/ExchangeConnect_V2_Trunk_Maven_workspace/ServiceCentre/bin/*
1 . file:/c:/TestService-1.0.jar

2没有权限,1有权限,使用doPrivileged后,不检查2



看一下java.security.AccessController的JavaDoc:

A caller can be marked as being  " privileged "  (see doPrivileged and below). When making access control decisions, the checkPermission method stops checking  if  it reaches a caller that was marked as  " privileged "  via a doPrivileged call without a context argument (see below  for  information about a context argument). If that caller ' s domain has the specified permission, no further checking is done and checkPermission returns quietly, indicating that the requested access is allowed. If that domain does not have the specified permission, an exception is thrown, as usual. 

其中提到的no further checking is done的意思是指stack中的checking

加入一个TestService2,文件操作在1,stack为(1,2,3为checking顺序)
3 . file:/D:/Workspaces/ExchangeConnect_V2_Trunk_Maven_workspace/ServiceCentre/bin/*
2 . file:/c:/TestService-1.0.jar
1.  file:/c:/TestService2-1.0.jar
 checking顺序为  1->2->3
如果doPrivileged是在2中调用,那么1,2需要具有权限,3不再进行检查
如果doPrivileged是在1中调用,那么1需要具有权限,2,3不再进行检查


总结:
1.  这里容易理解错误的地方是checking顺序,例如一个调用链 MethodA->MethodB->MethodC(这里的3个方法需要在3个不同的ProtectionDomain中),doPrivileged在MethodB中,很容易理解成检查A,B而不检查C,实际上stack中检查顺序为C->B->A,也就是检查C,B而不检查A

2. ServiceCentre不需要太多权限,而Service就需要使用doPrivileged来避免受到ServiceCentre的权限限制(如果service有足够的权限),Equinox中有很多这样的例子(Equinox扮演Service的角色)。


来自不同的位置的代码可以由一个CodeSource对象描述其位置和签名证书。根据代码的CodeSource的不同,代码拥有不同的权限。例如所有Java SDK自带的代码都具有所有的权限,而Applet中的代码则具有非常受限的权限,用户编写的代码可以自己定制权限(通过SecurityManager)。
当执行一段代码时,这段代码的StackTrace包含了从Main开始所有正在被调用而且没有结束的方法。在这个调用过程中,很有可能出现跨多个不同的CodeSource的调用序列。由于CodeSource不同,这些代码通常拥有不同的权限集。只有所有途经的CodeSource都具有对应的权限集合时,当前正在运行的代码才能存取某个Resource。
而doPrivileged方法是对这个规则的一种补充。他类似于Unix中的setuid程序。Unix中的login程序必须访问password文件从而获得用户授权信息,但是用户不能随意的访问password文件。因此,login程序具有setuid位,它不管被哪个用户所调用,都具有root的权限。
调用doPrivileged的方法不管其StackTrace中其他方法的权限,而仅仅根据当前方法的权限来判断用户是否能访问某个resource。也即可以规定用户只能用某种预定的方式来访问其本来不能访问的resource。
使用doPrivileged方法和使用setuid位都有需要注意的地方,例如仅执行必要的操作。否则,可能带来安全上的问题。

### 回答1: accesscontroller.doprivileged是Java中的一个方法,用于执行受保护的代码块,需要具有特定的权限才能执行。这个方法可以在Java安全管理器中使用,以确保代码的安全性和可靠性。具体来说,它可以用于执行需要访问系统资源或执行敏感操作的代码,例如读取或写入文件、访问网络等。在执行受保护的代码块之前,需要使用AccessController类的doPrivileged方法来获取特定的权限,以确保代码的安全性和可靠性。 ### 回答2: accesscontroller.doprivileged是Java中的一个方法,它可以让Java程序在安全管理器的限制下执行特权操作,即允许程序访问受保护的资源。 当程序需要执行一些系统级任务时,例如读取系统属性或者操作文件系统等,通常需要使用特权操作。但是,在使用特权操作之前,程序需要获取安全管理器的相应权限。 accesscontroller.doprivileged方法可以帮助程序获取到这些权限,实现特权操作。当程序调用这个方法时,它可以在安全管理器的限制下执行受保护的操作,而不会触发安全异常。这个方法可以帮助程序在执行操作时,更加灵活和安全。 在使用accesscontroller.doprivileged方法时,需要注意以下几点: 1. 这个方法只能在Java安全管理器环境下执行。 2. 应该将要执行的代码块作为PrivilegedAction对象传递给这个方法,从而确保代码块在安全管理器环境下执行。 3. 在使用这个方法时,应该明确需要的权限,确保程序可以进行特权操作。 通过使用accesscontroller.doprivileged方法,Java程序可以更加方便地进行特权操作,同时确保程序安全性。 ### 回答3: AccessController.doPrivileged是Java中的一个授权机制,它允许开发人员在代码中指定一段受保护的代码,从而具有执行特权操作的能力。这个机制的作用是为了防止恶意代码或者其他不安全的代码获取系统中的敏感信息或者执行不允许的操作。 这个授权机制的工作原理是,当一段代码包含了AccessController.doPrivileged方法时,这段代码可以在一种受保护的环境下运行,获得执行特权操作的能力。在使用这个机制时,通过doPrivileged方法指定执行特权代码的具体逻辑,该方法接受一个PrivilegedAction对象作为参数,并且这个对象包含了执行所需的具体代码。 doPrivileged方法中还提供了一个重载版本,可以接受额外的参数,包括执行特权代码所需要的访问控制上下文、执行代码的类加载器等信息。这些参数可以让开发人员更加灵活地指定执行方式,保护代码的安全性。 最后,需要注意的是,AccessController.doPrivileged只有在代码签名正确并且信任链可靠的情况下才能起到有效的保护作用。如果代码签名出现问题或者信任链被破坏,那么使用这个机制的代码也可能会遭受攻击。因此,在使用这个机制时,需要加强代码签名和信任链的管理,以确保代码的安全性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值