JavaFx WebView 如何添加自定义请求头?

参考:https://stackoverflow.com/questions/36917469/how-can-i-work-around-youtube-api-embed-restrictions-like-other-websites?answertab=active#tab-top

 

JavaFx的WebView请求头accept-language、accept-encoding、accept-charset这三个是无法更改的且不能添加自定义头信息,官方提供的接口只有更改UA。

JavaFx每次网络请求都会访问 prepreareConnection 方法,这样我们可用利用动态字节码技术在方法内部添加一些我们自己的代码,可以看到下方的源码,官方是通过 c.setRequestProperty 方法设置请求头的。

现在我们开始写代码,实现自定义头信息和覆盖官方头信息。

需要的jar包:ea-agent-loader、javassist

<dependency>
	<groupId>com.ea.agentloader</groupId>
	<artifactId>ea-agent-loader</artifactId>
	<version>1.0.3</version>
</dependency>
<dependency>
	<groupId>org.javassist</groupId>
	<artifactId>javassist</artifactId>
	<version>3.26.0-GA</version>
</dependency>

MyJavaAgent.java

import java.lang.instrument.Instrumentation;

public class MyJavaAgent {
    public static void agentmain(String agentArgument, Instrumentation instrumentation) {
        ClassTransformer transformer = new ClassTransformer();
        instrumentation.addTransformer(transformer);
    }
}

ClassTransformer.java

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;

import java.io.ByteArrayInputStream;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;

public class ClassTransformer implements ClassFileTransformer {
    @Override
    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
        byte[] byteCode = classfileBuffer;
        // javaFx webview 请求是通过这个类进行加载的
        if ("com/sun/webkit/network/URLLoader".equals(className)) {
            try {
                ClassPool classPool = new ClassPool(true);
                CtClass ctClass = classPool.makeClass(new ByteArrayInputStream(classfileBuffer));
                // 要修改的方法,因为设置请求头是在这个方法里面设置的
                CtMethod method = ctClass.getDeclaredMethod("prepareConnection");
                StringBuilder sb = new StringBuilder();
                // 注入代码 $1 表示此方法的第一个参数
                sb.append("$1.setRequestProperty(\"Referer\", \"https://www.baidu.com/\");");
                // 在代码最前面注入代码
                method.insertBefore(sb.toString());
                byteCode = ctClass.toBytecode();
                ctClass.detach();
            }  catch (Exception e) {
                e.printStackTrace();
            }
        }   
        return byteCode;
    }
}

Main.java

public static void main(String[] args) {
       // 在main方法的第一行执行
       AgentLoader.loadAgentClass(MyJavaAgent.class.getName(), null);
       launch(args);
}

这时候,我们启动程序来看下效果。

可以看到,我们已经成功注入的自定义头信息,那如何覆盖官方的accept-language、accept-encoding呢?很简单只需要改动 ClassTransformer.java transform 方法里面的 method.insertBefore 改成 method.insertAfter 即可覆盖

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值