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 方法设置请求头的。

JavaFx WebView 如何添加自定义请求头?_第1张图片

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

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


	com.ea.agentloader
	ea-agent-loader
	1.0.3


	org.javassist
	javassist
	3.26.0-GA

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 即可覆盖

你可能感兴趣的:(javafx,webview)