首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ByteBuddy rebasing、合成类型和OSGi

ByteBuddy rebasing、合成类型和OSGi
EN

Stack Overflow用户
提问于 2019-10-15 14:10:04
回答 2查看 224关注 0票数 2

我有以下为字节伙伴开发的拦截器:

代码语言:javascript
复制
public class SecurityInterceptor() {

    @RuntimeType
    public static Object intercept(
        @SuperCall Callable<Object> supercall, 
        @This Object target, 
        @Origin Method method, 
        @AllArguments Object[] args) {  

        // Check args and annotations ...       

        Object obj = supercall.call();

        // Post-process obj content ...
    }
}

拦截器注册如下:

代码语言:javascript
复制
Unloaded<Object> unloaded = new ByteBuddy()
    .rebase(type, classFileLocator)
    .method(ElementMatchers.isAnnotatedWith(Secured.class))
    .intercept(MethodDelegation.to(SecurityInterceptor.class))
    .make();
wovenClass.setBytes(unloaded.getBytes());

这发生在OSGi中的WeavingHook中。问题是,使用@SuperCall重新建立基址会改变原始代码

代码语言:javascript
复制
public User getUser(final String s) throws Exception {
    return SecurityInterceptor.intercept((Callable)new UsersServiceImpl$auxiliary$xhbBRSr4(this, s), 
        (Object)this, UsersServiceImpl.cachedValue$nlgHrwy3$sn5qca3, new Object[] { s });
}

其中UsersServiceImpl$auxiliary$xhbBRSr4是由字节伙伴生成的合成类:

代码语言:javascript
复制
class UsersServiceImpl$auxiliary$xhbBRSr4 implements Runnable, Callable
{
    private UsersServiceImpl argument0;
    private String argument1;

    @Override
    public Object call() throws Exception {
        return this.argument0.getUser$original$6ve6X5gN$accessor$nlgHrwy3(this.argument1);
    }

    @Override
    public void run() {
        this.argument0.getUser$original$6ve6X5gN$accessor$nlgHrwy3(this.argument1);
    }

    UsersServiceImpl$auxiliary$xhbBRSr4(final UsersServiceImpl argument0, final String argument2) {
        this.argument0 = argument0;
        this.argument1 = argument2;
    }
}

其中UsersServiceImpl是正在编织的类。

所以我需要的是将所有这些合成类添加到UsersServiceImpl包的类空间中(或者通常使合成类可以从该包中“访问”)。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-10-17 17:10:46

最后我使用了一种不同的方法:

代码语言:javascript
复制
Unloaded<Object> unloaded = new ByteBuddy()
    .redefine(type, classFileLocator)
    .visit(Advice.to(SecurityAdvice.class)
            .on(ElementMatchers.isAnnotatedWith(Secured.class)))
    .make();

使用

代码语言:javascript
复制
public class SecurityAdvice {
    @Advice.OnMethodEnter
    private static void enter(@Advice.AllArguments Object[] args) {
        //...
    }

    @Advice.OnMethodExit
    private static void exit(@Advice.Return(typing = Typing.DYNAMIC) Object value) {
       //...
    }
}

这只会改变原始类的字节码,而不会引入额外的合成类型。

票数 1
EN

Stack Overflow用户

发布于 2019-10-15 14:37:31

您可以应用的一个技巧是不使用create,而是在加载代理的过程中创建自己的类加载器,其中新类(及其所有合成类)被加载到具有多个父类的类加载器中:

代码语言:javascript
复制
dynamicType
  .make()
  .load(new MultipleParentClassLoader.Builder(false)
    .append(type.getClassLoader(), SecurityInterceptor.class.getClassLoader())
    .build());

代理类现在将被加载到一个新的类加载器中,该类加载器具有多个父类;屏蔽捆绑包通常不知道的任何其他类型的OSGi加载器,以及您自己的安全拦截器的类加载器。然而,多父类加载器将从两个类加载器请求任何类型,从而使这两个类对代理类都可见。

请注意构建器构造函数的false参数。这解封了类加载器,使其可能容易受到其他类的注入。我不认为您的代理类对反射攻击敏感,但这是需要考虑的问题。您可以删除该标志,并为类生成支付稍微高一点的成本。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58388214

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档