我为字节伙伴开发了以下拦截器:
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
包的类空间中添加所有这些综合类(或通常使该类中的“可访问”综合类)。这可能吗?
答案 0 :(得分:0)
您可以应用的一个技巧是在代理加载期间不使用重定基础,而是创建自己的类加载器,在该代理中,新类(及其所有合成类)将被加载到具有多个父级的类加载器中:>
dynamicType
.make()
.load(new MultipleParentClassLoader.Builder(false)
.append(type.getClassLoader(), SecurityInterceptor.class.getClassLoader())
.build());
现在,代理类将被加载到具有多个父级的新类加载器中; OSGi加载程序可以屏蔽捆绑软件通常不知道的任何其他类型,也可以是安全拦截器的类加载程序。但是,多父类加载器将向两个类加载器请求任何类型,从而使两者对于代理类都是可见的。
将false
参数通知构建者的构造函数。这使类加载器解封,使其可能容易受到其他类的注入的攻击。我不认为您的代理类对反射攻击敏感,但这是需要考虑的事情。您可以删除该标志,并为生成类支付更高的费用。
答案 1 :(得分:0)
最后,我使用了另一种方法:
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) {
//...
}
}
这只会更改原始类的字节码,而不会引入其他合成类型。