我有以下为字节伙伴开发的拦截器:
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 ...
}
}拦截器注册如下:
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重新建立基址会改变原始代码
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是由字节伙伴生成的合成类:
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包的类空间中(或者通常使合成类可以从该包中“访问”)。
发布于 2019-10-17 17:10:46
最后我使用了一种不同的方法:
Unloaded<Object> unloaded = new ByteBuddy()
.redefine(type, classFileLocator)
.visit(Advice.to(SecurityAdvice.class)
.on(ElementMatchers.isAnnotatedWith(Secured.class)))
.make();使用
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) {
//...
}
}这只会改变原始类的字节码,而不会引入额外的合成类型。
发布于 2019-10-15 14:37:31
您可以应用的一个技巧是不使用create,而是在加载代理的过程中创建自己的类加载器,其中新类(及其所有合成类)被加载到具有多个父类的类加载器中:
dynamicType
.make()
.load(new MultipleParentClassLoader.Builder(false)
.append(type.getClassLoader(), SecurityInterceptor.class.getClassLoader())
.build());代理类现在将被加载到一个新的类加载器中,该类加载器具有多个父类;屏蔽捆绑包通常不知道的任何其他类型的OSGi加载器,以及您自己的安全拦截器的类加载器。然而,多父类加载器将从两个类加载器请求任何类型,从而使这两个类对代理类都可见。
请注意构建器构造函数的false参数。这解封了类加载器,使其可能容易受到其他类的注入。我不认为您的代理类对反射攻击敏感,但这是需要考虑的问题。您可以删除该标志,并为类生成支付稍微高一点的成本。
https://stackoverflow.com/questions/58388214
复制相似问题