使用 SecurityManager 的性能损失是什么(如果有)

发布于 2024-12-17 09:13:46 字数 912 浏览 1 评论 0原文

使用 SecurityManager 时会有性能损失吗?

我需要以下信息:

public class ExitHelper {

    public ExitHelper() {

        System.setSecurityManager(new ExitMonitorSecurityManager());

    }

    private static class ExitMonitorSecurityManager extends SecurityManager {

        @Override
        public void checkPermission(Permission perm) {}

        @Override
        public void checkPermission(Permission perm, Object context) {}

        @Override
        public void checkExit( final int status ) {
            // this is the part I need and I don't care much about the performance issue of this method
        }
}

这会对我的计划产生巨大影响吗?

例如,该程序确实打开了很多文件。如果我启用 SecurityManager 并在那里添加一些日志记录,我可以发现这些方法被多次调用。真的很多。这两种方法的日志记录都丢失了正常的日志记录。因此,部署 SecurityManager 似乎意味着要进行大量的调用。它会比默认的 SecurityManager 慢吗? (默认有吗?)

这是如何工作的?将检查程序的哪一部分的权限以及多久一次?我担心两个 checkPermission(...) 方法。

Is there a performance penalty when using a SecurityManager?

I need the following:

public class ExitHelper {

    public ExitHelper() {

        System.setSecurityManager(new ExitMonitorSecurityManager());

    }

    private static class ExitMonitorSecurityManager extends SecurityManager {

        @Override
        public void checkPermission(Permission perm) {}

        @Override
        public void checkPermission(Permission perm, Object context) {}

        @Override
        public void checkExit( final int status ) {
            // this is the part I need and I don't care much about the performance issue of this method
        }
}

Will this have a huge impact on my program?

The program does open a lot of files, for example. And if I enable the SecurityManager and put some logging in there, I can that these methods are called a lot. Really a lot. So much that normal logging is lost amongst logging from these two methods. So it seems putting a SecurityManager into place means that lots and lots of calls are made. Would it be any slower than the default SecurityManager? (is there any by default?)

How does this work? Which part of the program will be checked for permissions and how often? I'm concerned by the two checkPermission(...) methods.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

执妄 2024-12-24 09:13:46

存在性能损失,但可能很小,因为:

  • 它仅适用于您尝试某种需要权限检查的活动形式。
  • 大多数需要权限检查的操作都是昂贵的操作(IO、网络访问等),因此安全检查的开销可能只占总运行时间的相当低的百分比。
  • 检查本身可以非常便宜地进行

。特别要注意的是,安全检查的调用代码在 Java 库代码中通常是非常轻量级的,即如下所示:

 SecurityManager security = System.getSecurityManager();
 if (security != null) {
     security.checkXXX(argument,  . . . );
 }

如果您的安全管理器代码本身同样是轻量级的,那么安全检查应该可以忽略不计。不过,我会避免将任何日志记录代码放入 SecurityManager 本身 - 这将是昂贵的,并且可能属于应用程序代码中的更高级别。

如果您想绝对最小化安全管理器对您不关心的权限的开销,那么您应该使用以下内容覆盖您不需要的特定 checkXXX 方法:

@Override 
public void checkRead(String file) {
  // empty method as we are happy to allow all file reads
}

最终您必须对您的特定权限进行基准测试情况,但“直觉”的答案是你不应该真正担心它。

There is a performance penalty, but it is likely to be small because:

  • It only applies when you attempt some form of activity that requires a permission check.
  • Most operations that require permission checks are expensive operations (IO, network access etc.), so it is likely that the overhead of security checks is going to be a pretty low percentage of total runtime.
  • The check itself can be made very cheaply

In particular, note that the calling code for security checks is typically very lightweight in the Java library code, i.e. something like this:

 SecurityManager security = System.getSecurityManager();
 if (security != null) {
     security.checkXXX(argument,  . . . );
 }

If your security manager code itself is equally lightweight, then the runtime cost of the security check should be negligible. I would avoid putting any logging code in the SecurityManager itself however - this would be costly and probably belongs at a higher level in your application code.

If you want to absolutely minimise the overhead of the security manager for permissions that you don't care about, then you should override the specific checkXXX methods that you don't need with something like:

@Override 
public void checkRead(String file) {
  // empty method as we are happy to allow all file reads
}

Ultimately you'll have to benchmark for your particular situation, but the "gut feel" answer would be that you shouldn't really be worrying about it.

一江春梦 2024-12-24 09:13:46

是的,存在性能损失。如果你担心的话,你唯一的办法就是衡量一下,看看惩罚是否太高。

针对您的特定用例的一种潜在解决方案是,您是否可以缩小需要时的范围。您显然想要阻止某些您无法控制的代码退出应用程序。如果您知道何时可以调用该代码,那么您可以在该调用期间设置安全管理器(注意,您需要注意此处的线程影响,因为安全管理器设置是全局的),例如:

System.setSecurityManager(new ExitMonitorSecurityManager());
try {
  // ... do protected op here ...
} finally {
  System.setSecurityManager(null);
}

更新:

为了向那些稍后可能会看到这个答案的人澄清,这个答案不是为处理潜在的恶意代码而设计的。在这种情况下,适当配置的 SecurityManager 应始终到位。这个答案假设OP正在尝试处理一个编写得不好的第三方库,该库在某个定义良好的时间点对System.exit()进行了不幸的调用。

yes there is a performance penalty. if you are concerned about it, your only recourse is to measure it and see if the penalty is too high.

one potential solution for your specific use case is if you can narrow the scope of when it's needed. you clearly want to stop some code which you don't control from exiting the application. if you know when that code could be invoked, then you can just set the security manager during that call (note, you need to be aware of threading affects here since the security manager setting is global), e.g.:

System.setSecurityManager(new ExitMonitorSecurityManager());
try {
  // ... do protected op here ...
} finally {
  System.setSecurityManager(null);
}

UPDATE:

to clarify to those who may be coming to this answer later, this answer is not designed for dealing with potentially malicious code. In that situation, an appropriately configured SecurityManager should be in place at all times. This answer assumes that the OP is trying to deal with a poorly written third-party library which makes an unfortunate call to System.exit() at some, well defined point in time.

断肠人 2024-12-24 09:13:46

在实现安全管理器问题后,我有一些经验证据可以在这里贡献:

一个 java SecurityManager 与 NO 安全管理器相同,除了 System.exit 的单个检查调整

这个匿名内部类的性能影响是巨大的:

        System.setSecurityManager(new SecurityManager() {
            @Override
            public void checkPermission(Permission perm) {
                return; // no security manager behaviour
            }

            @Override
            public void checkPermission(Permission perm, Object context) {
                return; // no security manager behaviour
            }

            @Override
            public void checkExit(int status) {
                Thread.dumpStack();
                super.checkExit(status);
            }
        });

我的经验启动我的应用程序在 Eclipse 中,它明显变慢,我在同事的 PC 上也确认了同样的情况。

所以我觉得“可以忽略不计”可能是一个轻描淡写的说法(我的用例甚至没有实际执行任何检查!)。将此视为轶事,但事实并非如此。

作为另一个旁注:我创建了一个最终类,对所有方法都不做任何检查,以避免实例化权限对象等(最终鼓励 jit 编译器热连接它)。使用这种方法,对性能的影响确实很小。因此,对于只想添加一些特定检查(而不依赖于 java 策略)的人来说,这实际上确实具有可以忽略不计的影响:

public final class SystemExitTraceSecurityManager extends SecurityManager {

    @Override
    public final void checkAccept(String host, int port) {
    }

    @Override
    public final void checkAccess(Thread t) {
    }

    @Override
    public final void checkAccess(ThreadGroup g) {
    }

    @Override
    public final void checkAwtEventQueueAccess() {
    }

    @Override
    public final void checkConnect(String host, int port) {
    }

    @Override
    public final void checkConnect(String host, int port, Object context) {
    }

    @Override
    public final void checkCreateClassLoader() {
    }

    public final void checkDelete(String file) {
    };

    @Override
    public final void checkExec(String cmd) {
    }

    public final void checkExit(int status) {
        Thread.dumpStack();
    };

    @Override
    public final void checkLink(String lib) {
    }

    @Override
    public final void checkListen(int port) {
    }

    @Override
    public final void checkMemberAccess(Class<?> clazz, int which) {
    }

    @Override
    public final void checkMulticast(InetAddress maddr) {
    }

    @Override
    public final void checkMulticast(InetAddress maddr, byte ttl) {
    }

    @Override
    public final void checkPackageAccess(String pkg) {
    }

    @Override
    public final void checkPackageDefinition(String pkg) {
    }

    @Override
    public final void checkPermission(Permission perm) {
    }

    @Override
    public final void checkPermission(Permission perm, Object context) {
    }

    @Override
    public final void checkPrintJobAccess() {
    }

    @Override
    public final void checkPropertiesAccess() {
    }

    public final void checkPropertyAccess(String key) {
    };

    @Override
    public final void checkRead(FileDescriptor fd) {
    }

    @Override
    public final void checkRead(String file) {
    }

    @Override
    public final void checkRead(String file, Object context) {
    }

    @Override
    public final void checkSecurityAccess(String target) {
    }

    @Override
    public final void checkSetFactory() {
    }

    @Override
    public final void checkSystemClipboardAccess() {
    }

    @Override
    public final boolean checkTopLevelWindow(Object window) {
        return true;
    }

    @Override
    public final void checkWrite(FileDescriptor fd) {
    }

    @Override
    public final void checkWrite(String file) {
    }
}

I have some empirical evidence to contribute here, after implementing the security manager question:

A java SecurityManager that is identical to NO security manager except for a single check adjustment for System.exit

The performance impact with this anonymous inner class was HUGE:

        System.setSecurityManager(new SecurityManager() {
            @Override
            public void checkPermission(Permission perm) {
                return; // no security manager behaviour
            }

            @Override
            public void checkPermission(Permission perm, Object context) {
                return; // no security manager behaviour
            }

            @Override
            public void checkExit(int status) {
                Thread.dumpStack();
                super.checkExit(status);
            }
        });

My experience after launching my application in Eclipse was that it was visibly slower and I confirmed the same in a colleague's PC.

So I feel that 'negligible' may be an understatement (and my use case does not even actually perform any checks!). Consider this as an anecdote that this is not the case.

As another side note: I created a final class with do-nothing checks for ALL methods to avoid instantiating permission objects and such (end encourage the jit compiler to hot-wire it). Using this approach, the performance impact was indeed minimal. So, for people that simply want to add a couple of specific checks (and not rely on java policies) this actually does have negligible impact:

public final class SystemExitTraceSecurityManager extends SecurityManager {

    @Override
    public final void checkAccept(String host, int port) {
    }

    @Override
    public final void checkAccess(Thread t) {
    }

    @Override
    public final void checkAccess(ThreadGroup g) {
    }

    @Override
    public final void checkAwtEventQueueAccess() {
    }

    @Override
    public final void checkConnect(String host, int port) {
    }

    @Override
    public final void checkConnect(String host, int port, Object context) {
    }

    @Override
    public final void checkCreateClassLoader() {
    }

    public final void checkDelete(String file) {
    };

    @Override
    public final void checkExec(String cmd) {
    }

    public final void checkExit(int status) {
        Thread.dumpStack();
    };

    @Override
    public final void checkLink(String lib) {
    }

    @Override
    public final void checkListen(int port) {
    }

    @Override
    public final void checkMemberAccess(Class<?> clazz, int which) {
    }

    @Override
    public final void checkMulticast(InetAddress maddr) {
    }

    @Override
    public final void checkMulticast(InetAddress maddr, byte ttl) {
    }

    @Override
    public final void checkPackageAccess(String pkg) {
    }

    @Override
    public final void checkPackageDefinition(String pkg) {
    }

    @Override
    public final void checkPermission(Permission perm) {
    }

    @Override
    public final void checkPermission(Permission perm, Object context) {
    }

    @Override
    public final void checkPrintJobAccess() {
    }

    @Override
    public final void checkPropertiesAccess() {
    }

    public final void checkPropertyAccess(String key) {
    };

    @Override
    public final void checkRead(FileDescriptor fd) {
    }

    @Override
    public final void checkRead(String file) {
    }

    @Override
    public final void checkRead(String file, Object context) {
    }

    @Override
    public final void checkSecurityAccess(String target) {
    }

    @Override
    public final void checkSetFactory() {
    }

    @Override
    public final void checkSystemClipboardAccess() {
    }

    @Override
    public final boolean checkTopLevelWindow(Object window) {
        return true;
    }

    @Override
    public final void checkWrite(FileDescriptor fd) {
    }

    @Override
    public final void checkWrite(String file) {
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文