java之jvm学习笔记四(安全管理器)

               欢迎装载请说明出处:http://blog.csdn.net/yfqnihao

               前面已经简述了java的安全模型的两个组成部分(类装载器,class文件校验器),接下来学习的是java安全模型的另外一个重要组成部分安全管理器。

               安全管理器是一个单独的对象,在java虚拟机中,它在访问控制-对于外部资源的访问控制-起到中枢作用

                如果光看概念可能并不能很好的理解,或者说比较抽象,下面是ClassLoader其中的一个构造函数,先简单的看看它在初始化ClassLoader之前会做一些什么操作

               


   
   
  1. protected ClassLoader (ClassLoader parent) {
  2. SecurityManager security = System.getSecurityManager();
  3. if (security != null) {
  4. security.checkCreateClassLoader();
  5. }
  6. this.parent = parent;
  7. initialized = true;
  8. }



这个构造函数的第一话(当然还有隐式调用)就是System.getSecurityManager();这行代码返回的就是一个安全管理器对象security,这个对象所属的目录为java.lang.SecurityManager。

这个构造函数先判断如果已经安装了安全管理器security(在前面类装载器的章节,我们提到过,类装载器和安全管理器是可以由用户定制的,在这里有了体现吧!!既然有System.getSecurityManager();你当然也应该猜到有System.setSecurityManager();),也就是安全管理器不为空,那么就执行校验,跳到checkCreateClassLoader();看看他做的是什么操作


   
   
  1. public void checkCreateClassLoader () {
  2. checkPermission(SecurityConstants.CREATE_CLASSLOADER_PERMISSION);
  3. }

 


这里又调用了另外一个方法,从方法名字上,就可以猜到这个方法是用来校验权限的,校验是否有创建ClassLoader的权限,再跳到checkPermisson方法里

 


   
   
  1. public static void checkPermission (Permission perm)
  2. throws AccessControlException
  3. {
  4. //System.err.println("checkPermission "+perm);
  5. //Thread.currentThread().dumpStack(); if (perm == null) {
  6. throw new NullPointerException( "permission can't be null");
  7. } AccessControlContext stack = getStackAccessControlContext();
  8. // if context is null, we had privileged system code on the stack.
  9. if (stack == null) {
  10. Debug debug = AccessControlContext.getDebug();
  11. boolean dumpDebug = false;
  12. if (debug != null) {
  13. dumpDebug = !Debug.isOn( "codebase=");
  14. dumpDebug &= !Debug.isOn( "permission=") ||
  15. Debug.isOn( "permission=" + perm.getClass().getCanonicalName());
  16. } if (dumpDebug && Debug.isOn( "stack")) {
  17. Thread.currentThread().dumpStack();
  18. } if (dumpDebug && Debug.isOn( "domain")) {
  19. debug.println( "domain (context is null)");
  20. } if (dumpDebug) {
  21. debug.println( "access allowed "+perm);
  22. }
  23. return;
  24. } AccessControlContext acc = stack.optimize();
  25. acc.checkPermission(perm);
  26. }
  27. }


 


 

上面的这个方法有些代码比较难以理解,我们不用每行都读懂(这个方法涉及的东西比较多,它涉及到了代码签名认证,策略还有保护域,这些我们在后一节中会详细的讲解,看不懂先跳过),看它的注解// if context is null, we had privileged system code on the stack.意思就是如果当前的访问控制器上下文为空,在栈上的系统代码将得到特权,找到acc.checkPermission(perm);再跳进去找到下面这段代码

 


   
   
  1. /*
  2. * iterate through the ProtectionDomains in the context.
  3. * Stop at the first one that doesn't allow the
  4. * requested permission (throwing an exception).
  5. *
  6. */ /* if ctxt is null, all we had on the stack were system domains,
  7. or the first domain was a Privileged system domain. This
  8. is to make the common case for system code very fast */ if (context == null)
  9. return; for ( int i= 0; i< context.length; i++) {
  10. if (context[i] != null && !context[i].implies(perm)) {
  11. if (dumpDebug) {
  12. debug.println( "access denied " + perm);
  13. } if (Debug.isOn( "failure") && debug != null) {
  14. // Want to make sure this is always displayed for failure,
  15. // but do not want to display again if already displayed
  16. // above.
  17. if (!dumpDebug) {
  18. debug.println( "access denied " + perm);
  19. }
  20. Thread.currentThread().dumpStack();
  21. final ProtectionDomain pd = context[i];
  22. final Debug db = debug;
  23. AccessController.doPrivileged ( new PrivilegedAction() {
  24. public Object run () {
  25. db.println( "domain that failed "+pd);
  26. return null;
  27. }
  28. });
  29. }
  30. throw new AccessControlException( "access denied "+perm, perm);
  31. }
  32. }


 


 

什么都不用看,就看最上面的那段注解,意思是遍历上下文中的保护域,一旦发现请求的权限不被允许,停止,抛出异常,到这里我们有一个比较清晰的概念了,安全管理器就是用来控制执行权限的,而上面的这段代码中有一个很重要的类 AccessController,访问控制器,还有一个很重要的名词保护域(保护域我们在前面一节也有简单的带过一下,是不是有点印象),这些可能现在听有点模糊,不要担心,暂时不要管,后面一章节慢慢的会对他们进行讲解。


好了了解安全管理器是做什么的之后,接下来,来做一个下的实验,先来验证,默认安全管理是没有被安装的,接着来试着把他安装上去。在我的环境中我是没有安装默认的安全管理器的,也没有基于默认的安全管理器写自己的安全管理器,如果需要打开的话,可以在程序显示的安装安全管理器,同样可以让它自动安装默认的安全管理器(给jvm加上-Djava.security.manager就可以了。

下面我们用熟悉的ecplise写一个简单的demo来看看安装前后的区别,在下一节中,会详细的来学习代码签名认证和策略,并写一个自己的安全管理器。


   
   
  1. public static void main (String[] args) {
  2. System.out.println(System.getSecurityManager());
  3. }

运行这个main函数,输出什么?是的输出null,这个时候我们没有安装默认的安全管理器

重新换个方式运行,在ecplise里右键--Run As--Run Configuration--Arguments,在VM arguments的栏目里输入

-Djava.security.manager。在点击Run,这个时候看到什么?

输出:securityManager的对象名。这个时候默认的安全管理器就被安装上了。

 

总结:

      在java虚拟机中,它在访问控制-对于外部资源的访问控制-起到中枢作用

 

writed by:keycoding

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值