java調(diào)用js文件的兩種常用方法示例(支持V8引擎)
前言
對java逆向感興趣的盆友可以關(guān)注我以前的文章,有圖片驗(yàn)證碼識別、AES、SHA256等各種加密的java實(shí)現(xiàn),不定時(shí)更新常用算法和加密,歡迎一起交流討論!
在日常逆向中,一些前端的加密代碼用java復(fù)現(xiàn)出來比較難,所以經(jīng)常需要調(diào)用js文件來實(shí)現(xiàn)加密操作,接下來將介紹兩種常用調(diào)用js的思路,第一種適用于普通js文件,第二種則適用于比較新的V8引擎。在實(shí)現(xiàn)的過程中,也會展示可能遇到的問題以及解決辦法,廢話不多話,正文開始!
方法一
本方法用的是jdk自帶的ScriptEngine
來實(shí)現(xiàn),大概流程是:加載引擎->綁定環(huán)境->預(yù)編譯js文件->調(diào)用文件內(nèi)方法,具體實(shí)現(xiàn)代碼:
import javax.script.*; import java.io.InputStreamReader; //因?yàn)閖s文件讀取一次就行,因此用靜態(tài)代碼塊來讀取 private static ScriptEngine engine; static { try { ScriptEngineManager manager = new ScriptEngineManager(); engine = manager.getEngineByName("javascript"); Bindings engineScope = engine.getBindings(ScriptContext.ENGINE_SCOPE); engineScope.put("window", engineScope); engineScope.put("navigator", engineScope); InputStreamReader jsencryptFileReader = new InputStreamReader(EncJs.class.getClassLoader().getResourceAsStream("enc.js")); engine.eval(jsencryptFileReader); jsencryptFileReader.close(); } catch (Exception e) { e.printStackTrace(); } }
讀取完js后,就可以使用js引擎來直接用invokeFunction
方法來調(diào)用文件內(nèi)函數(shù),代碼如下
public static String enc(String data, String key) { Invocable invoke = (Invocable) engine; try { String result = (String) invoke.invokeFunction("Enc", data, key); return result.toUpperCase(); } catch (Exception e) { e.printStackTrace(); return null; } }
在上邊代碼invoke.invokeFunction("Enc", data, key)
中,Enc
為js文件內(nèi)的函數(shù)名,data
和key
是需要方法需要傳遞的參數(shù),如果方法只有一個(gè)參數(shù),則傳入一個(gè),如果是多個(gè)參數(shù),則按順序排列在后邊即可。
上邊代碼在執(zhí)行普通js時(shí)比較方便使用,但是如果是比較新的開發(fā)版本,有些語法會不支持,像lambda表達(dá)式等,如下圖:
此處再介紹一種方法,使用的是V8引擎,可以支持最新語法
方法二
使用到的maven依賴,以下依賴根據(jù)自己環(huán)境任選其一即可。
<!-- linux系統(tǒng) --> <dependency> <groupId>com.eclipsesource.j2v8</groupId> <artifactId>j2v8_linux_x86_64</artifactId> <version>3.1.6</version> </dependency> <!-- mac系統(tǒng) --> <dependency> <groupId>com.eclipsesource.j2v8</groupId> <artifactId>j2v8_macosx_x86_64</artifactId> <version>4.6.0</version> </dependency> <!-- windows系統(tǒng) --> <dependency> <groupId>com.eclipsesource.j2v8</groupId> <artifactId>j2v8_win32_x86_64</artifactId> <version>4.6.0</version> </dependency>
這個(gè)的實(shí)現(xiàn)流程和上邊稍微有些不同,也是:預(yù)讀取js文件>加載引擎->編譯js文件->調(diào)用文件內(nèi)方法,具體實(shí)現(xiàn)代碼如下:
import com.eclipsesource.v8.V8; import org.apache.commons.io.IOUtils; import java.io.IOException; import java.nio.charset.StandardCharsets; public class V8JSUtils { private static String fileStr; static { try { fileStr = IOUtils.toString(V8JSUtils.class.getClassLoader().getResourceAsStream("enc.js"), StandardCharsets.UTF_8); } catch (IOException e) { e.printStackTrace(); } } public static String dec(String data, String key) { V8 runtime = V8.createV8Runtime(); try { runtime.executeVoidScript(fileStr); return (String) runtime.executeJSFunction("Dec", data, key); } catch (Exception e) { e.printStackTrace(); } finally { runtime.release(); } return null; } }
代碼寫完了,調(diào)用一下結(jié)果還是遇到了錯(cuò)誤
這個(gè)錯(cuò)誤的大概意思就是:嚴(yán)格模式外不能使用let,const之類的es6的命令,也就是說版本太低了,怎么辦,更新版本?no no no,找到JS文件出錯(cuò)的代碼位置,在方法前加上一句:'use strict';
注意!引號不能省略,必須全部復(fù)制,如圖
現(xiàn)在再運(yùn)行就正常了。
附:在Java中綁定js變量
在調(diào)用engine.get(key);時(shí),如果key沒有定義,則返回null
package com.sinaapp.manjushri; import javax.script.Bindings; import javax.script.ScriptContext; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; public class ScriptEngineTest2 { public static void main(String[] args) { ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine engine = manager.getEngineByName("javascript"); engine.put("a", 4); engine.put("b", 3); Bindings bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE); try { // 只能為Double,使用Float和Integer會拋出異常 Double result = (Double) engine.eval("a+b"); System.out.println("result = " + result); engine.eval("c=a+b"); Double c = (Double)engine.get("c"); System.out.println("c = " + c); } catch (ScriptException e) { e.printStackTrace(); } } }
輸出:
result = 7.0
c = 7.0
總結(jié)
到此這篇關(guān)于java調(diào)用js文件的兩種常用方法的文章就介紹到這了,更多相關(guān)java調(diào)用js文件的方法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot實(shí)現(xiàn)聯(lián)表查詢的代碼詳解
這篇文章主要介紹了SpringBoot中如何實(shí)現(xiàn)聯(lián)表查詢,文中通過代碼示例和圖文結(jié)合的方式講解的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-05-05基于JavaBean編輯器讀取peroperties文件的實(shí)例
下面小編就為大家?guī)硪黄贘avaBean編輯器讀取peroperties文件的實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-10-10spring+html5實(shí)現(xiàn)安全傳輸隨機(jī)數(shù)字密碼鍵盤
這篇文章主要為大家詳細(xì)介紹了spring html5實(shí)現(xiàn)安全傳輸隨機(jī)數(shù)字密碼鍵盤,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04將應(yīng)用程序進(jìn)行Spring6遷移的最佳使用方式
這篇文章主要介紹了將應(yīng)用程序進(jìn)行Spring6遷移的最佳方式,以及如何充分利用此升級,需要的朋友可以參考下,如有錯(cuò)誤的地方還請指正2023-03-03詳解Spring Aop實(shí)例之AspectJ注解配置
本篇文章主要介紹了詳解Spring Aop實(shí)例之AspectJ注解配置,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-04-04spring整合redis實(shí)現(xiàn)數(shù)據(jù)緩存的實(shí)例代碼
這篇文章主要介紹了spring整合redis實(shí)現(xiàn)數(shù)據(jù)緩存,需要的朋友可以參考下2018-09-09