Skip to content

Commit ce43a73

Browse files
authored
Merge pull request #17 from JSREI/dev
feat: 支持在断点时以人类可读形式展示当前请求的上下文
2 parents d8b469a + 2cbba59 commit ce43a73

File tree

12 files changed

+161
-5
lines changed

12 files changed

+161
-5
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
这是一个jsonp请求参数有加密的例子。
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
这是一个jsonp请求的响应被加密的例子。

goat/script-src-encrypt/README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
2+
3+
4+
5+
6+
这是一个script请求中携带加密参数的例子。
7+
8+
9+
10+
11+
12+
13+
14+
15+
16+

src/analyzer/request-analyzer.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class RequestAnalyzer {
1616
requestContext.params = this.computeParamsJsonpCallbackScore(requestContext.params);
1717

1818
// 选出其中可能性最大的一个参数作为jsonp callback参数
19-
if (requestContext.params && requestContext.params[0].jsonpCallbackScore > 0) {
19+
if (requestContext.params && requestContext.params.length && requestContext.params[0].jsonpCallbackScore > 0) {
2020
requestContext.params[0].isJsonpCallback = true;
2121
}
2222

src/config/config.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,15 @@ class Config {
99
* @param callbackFunctionParamName {String} 传递jsonp回调函数名字的参数,比如 "callback"
1010
*/
1111
constructor(urlPattern, callbackFunctionParamName) {
12+
1213
// 让用户能够自己指定前缀,也许会有一些拥有感?之前ast hook好像就有个哥们喜欢这样干...
1314
this.prefix = "CC11001100";
15+
16+
// 是否忽略.js后缀的请求
17+
this.isIgnoreJsSuffixRequest = true;
18+
19+
// 是否忽略不是jsonp的请求
20+
this.isIgnoreNotJsonpRequest = true;
1421
}
1522

1623
}

src/context/request/param.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
const {repeat} = require("../../utils/string-util");
2+
13
/**
24
* 表示url路径中的一个参数,对于script类型的请求来说,它只有query string类型的参数,因为它无法携带请求体
35
*/
@@ -23,6 +25,20 @@ class Param {
2325

2426
}
2527

28+
/**
29+
* 把参数转为适合人类阅读的样式
30+
*
31+
* @return {string}
32+
*/
33+
toHumanReadable(indent) {
34+
const indentString = repeat(" ", indent);
35+
if (this.isJsonpCallback) {
36+
return `${indentString}${this.name} = ${this.value} <---- this param is jsonp callback function name`
37+
} else {
38+
return `${indentString}${this.name} = ${this.value}`;
39+
}
40+
}
41+
2642
}
2743

2844
module.exports = {

src/context/request/request-context.js

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const {Param} = require("./param");
2+
const {repeat} = require("../../utils/string-util");
23

34
/**
45
* 用于封装请求的上下文
@@ -22,7 +23,8 @@ class RequestContext {
2223
this.host = host;
2324
this.port = port;
2425
this.path = path;
25-
this.params = params;
26+
// 避免为空
27+
this.params = params || [];
2628
this.hash = hash;
2729
}
2830

@@ -85,6 +87,37 @@ class RequestContext {
8587
return null;
8688
}
8789

90+
/**
91+
*
92+
* @return {""|boolean}
93+
*/
94+
isJsSuffixRequest() {
95+
return this.path && this.path.toLowerCase().endsWith(".js")
96+
}
97+
98+
/**
99+
* 转成方便阅读的格式
100+
*/
101+
toHumanReadable(indent) {
102+
103+
const indentSpace = repeat(" ", indent);
104+
105+
const msgs = [];
106+
msgs.push(`${indentSpace}hostname: ${this.hostname}`);
107+
msgs.push(`${indentSpace}path: ${this.path}`);
108+
109+
msgs.push(`${indentSpace}params: `);
110+
for (let param of this.params) {
111+
msgs.push(param.toHumanReadable(indent + 4));
112+
}
113+
114+
if (this.hash) {
115+
msgs.push(`${indentSpace}hash: ${this.hash}`)
116+
}
117+
118+
return msgs.join("\n\n");
119+
}
120+
88121
}
89122

90123
module.exports = {

src/context/response/response-context.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ class ResponseContext {
3131

3232
}
3333

34+
toHumanReadable() {
35+
return "";
36+
}
37+
3438
}
3539

3640
module.exports = {

src/context/script/script-context.js

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,45 @@ class ScriptContext {
2525
* @returns {boolean}
2626
*/
2727
isJsonp() {
28-
return this.responseContext.isJsonpResponse() || this.requestContext.isJsonpRequest();
28+
if (this.requestContext && this.requestContext.isJsonpRequest()) {
29+
return true;
30+
}
31+
if (this.responseContext && this.responseContext.isJsonpResponse()) {
32+
return true;
33+
}
34+
return false;
35+
}
36+
37+
/**
38+
* 判断是否是请求的js文件
39+
*
40+
* @return {""|boolean}
41+
*/
42+
isJsSuffixRequest() {
43+
return this.requestContext && this.requestContext.isJsSuffixRequest();
44+
}
45+
46+
/**
47+
*
48+
* @return {string}
49+
*/
50+
toHumanReadable() {
51+
52+
const msgs = [];
53+
54+
if (this.requestContext) {
55+
msgs.push("Request Information: ");
56+
msgs.push(this.requestContext.toHumanReadable(4));
57+
}
58+
59+
msgs.push("\n\n");
60+
61+
if (this.responseContext) {
62+
msgs.push("Response Information: ")
63+
msgs.push(this.responseContext.toHumanReadable(4));
64+
}
65+
66+
return msgs.join("\n\n");
2967
}
3068

3169
}

src/debugger/debugger.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
const {ObjectFunctionHook} = require("../hook/object-function-hook");
22
const {getUnsafeWindow} = require("../utils/scope-util");
33
const {JsonpCallbackFunctionAnalyzer} = require("../analyzer/response-analyzer");
4+
const {globalConfig} = require("../config/config");
45

56
/**
67
* 表示一个jsonp的条件断点
@@ -35,8 +36,23 @@ class Debugger {
3536
return;
3637
}
3738

39+
// 支持忽略js文件请求
40+
if (globalConfig.isIgnoreJsSuffixRequest && scriptContext.isJsSuffixRequest()) {
41+
return;
42+
}
43+
44+
// 忽略不是jsonp的请求
45+
if (globalConfig.isIgnoreNotJsonpRequest && !scriptContext.isJsonp()) {
46+
return;
47+
}
48+
3849
// 请求断点
3950
if (this.enableRequestDebugger) {
51+
// 把一些相关的上下文赋值到变量方便断点命中这里的时候观察
52+
// _scriptContext中存放的是与当前的script请求相关的一些上下文信息
53+
const _scriptContext = scriptContext;
54+
const humanReadableScriptInformation = scriptContext.toHumanReadable()
55+
console.log(humanReadableScriptInformation);
4056
debugger;
4157
}
4258

@@ -54,8 +70,15 @@ class Debugger {
5470
}
5571

5672
// 为响应体中的回调函数增加hook
73+
const jsonpCallbackFunction = getUnsafeWindow()[jsonpCallbackFunctionName];
74+
if (!jsonpCallbackFunction) {
75+
// TODO 2024-12-20 23:08:29 错误处理
76+
return;
77+
}
78+
// 跟进去这个 jsonpCallbackFunction 函数的代码位置就是jsonp的回调函数的逻辑,也是处理响应的逻辑
5779
new ObjectFunctionHook(getUnsafeWindow(), jsonpCallbackFunctionName).addHook(function () {
5880
// 这里是脚本的响应断点,已经拦截到响应,跟进去holder函数就行了
81+
console.log(jsonpCallbackFunction);
5982
debugger;
6083
});
6184
}

0 commit comments

Comments
 (0)