我是靠谱客的博主 昏睡钻石,最近开发中收集的这篇文章主要介绍@CallerSensitive 原理,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

关注公众号:码农架构。 回复资料,领取小码哥最新整理的面试资料

权限

  • Reflection.getCallerClass()此方法的调用者必须有权限,需要什么样的权限呢?
    • 由bootstrap class loader加载的类可以调用
    • 由extension class loader加载的类可以调用
  • 都知道用户路径的类加载都是由 application class loader进行加载的,换句话说就是用户自定义的一些类中无法调用此方法

作用

Reflection.getCallerClass()方法调用所在的方法必须用@CallerSensitive进行注解,通过此方法获取class时会跳过链路上所有的有@CallerSensitive注解的方法的类,直到遇到第一个未使用该注解的类,避免了用Reflection.getCallerClass(int n) 这个过时方法来自己做判断。

如何验证

  • 写一个jdk动态代理测试代码,然后断点在java.lang.Class#forName(java.lang.String, boolean, java.lang.ClassLoader) (这个方法有@CallerSensitive注解),然后手动执行Reflection.getCallerClass() 和 Reflection.getCallerClass(1) 方法,发现两者的结果是不一样的,而Reflection.getCallerClass() 结果为java.lang.reflect.Proxy$ProxyClassFactory,而Reflection.getCallerClass(1) 的结果是 java.lang.Class ,说明前者跳过了java.lang.Class,找到了java.lang.reflect.Proxy$ProxyClassFactory

@CallSensitive是JVM中专用的注解,在类加载过过程中是可以常常看到这个注解的身影的。
这是在Sun.reflect中的定义:

@Retention(RetentionPolicy.RUNTIME)
@Target({ java.lang.annotation.ElementType.METHOD })
public @interface CallerSensitive {
}

而对@CallSensitive的使用如下:

@CallerSensitive
    public final ClassLoader getParent() {
        if (this.parent == null)
            return null;
        SecurityManager localSecurityManager = System.getSecurityManager();
        if (localSecurityManager != null)
            checkClassLoaderPermission(this.parent, Reflection.getCallerClass());
        return this.parent;
    }

至少在刚刚看见这个注解时我是不明白@CallSensitive有什么用处,一来这是JVM里专用的一个注解,二来在JVM规范和一些书上也没有看到对这个注解的解释,第三是发现百度不出来对这个注解的解释。

这里有两个解释:
What does the sun.reflect.CallerSensitive annotation mean?
JEP 176: Mechanical Checking of Caller-Sensitive Methods

StackOverFlow里的回答,答案只是提到了@CallSensitive用来找到真正发起反射请求的类的,但没有提到具体怎么寻找的,而在OpenJDK文档里,有下面这句话。

When invoked via reflection, these methods must be handled specially in order to ensure that the class of the actual caller, rather than some class of the reflection mechanism itself, is returned by the getCallerClass method. The logic for doing this involves pattern matching against a hand-maintained list of caller-sensitive methods,

我原本的理解是这个注解用来区分开反射和自省的,并且只有调用方有这个注解我才会回应它,但感觉总有地方说不过去。所以我去问了导师

这个注解是为了堵住漏洞用的。曾经有黑客通过构造双重反射来提升权限,原理是当时反射只检查固定深度的调用者的类,看它有没有特权,例如固定看两层的调用者(getCallerClass(2))。如果我的类本来没足够权限群访问某些信息,那我就可以通过双重反射去达到目的:反射相关的类是有很高权限的,而在 我->反射1->反射2 这样的调用链上,反射2检查权限时看到的是反射1的类,这就被欺骗了,导致安全漏洞。使用CallerSensitive后,getCallerClass不再用固定深度去寻找actual caller(“我”),而是把所有跟反射相关的接口方法都标注上CallerSensitive,搜索时凡看到该注解都直接跳过,这样就有效解决了前面举例的问题

最后

以上就是昏睡钻石为你收集整理的@CallerSensitive 原理的全部内容,希望文章能够帮你解决@CallerSensitive 原理所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(49)

评论列表共有 0 条评论

立即
投稿
返回
顶部