写在前面
本文基于因体科技提供的测试服务撰写,如果你需要使用自己搭建的服务端,并且需要教程帮助,可以参考这篇文档:https://iinti.cn/sekiro-article/sekiro-js-4/
本文选用了一个 http 站点作为测试,如果您的目标站点是 https,请修改ws
为wss
并自行配置证书,参考 https://iinti.cn/sekiro-doc/02_advance/03_sslForWebsocket.html#%E9%85%8D%E7%BD%AE%E5%9F%9F%E5%90%8D%E5%88%97%E8%A1%A8
也可以直接咨询我们,可以提供 Saas ~
如果大家觉得 Sekiro 非常好用,欢迎联系我们合作~
编写油猴脚本
首先先创建一个新的油猴脚本
然后引入关键函数SekiroClient()
function SekiroClient(e) {
if (((this.wsURL = e), (this.handlers = {}), (this.socket = {}), !e))
throw new Error("wsURL can not be empty!!");
(this.webSocketFactory = this.resolveWebSocketFactory()), this.connect();
}
(SekiroClient.prototype.resolveWebSocketFactory = function () {
if ("object" == typeof window) {
var e = window.WebSocket ? window.WebSocket : window.MozWebSocket;
return function (o) {
function t(o) {
this.mSocket = new e(o);
}
return (
(t.prototype.close = function () {
this.mSocket.close();
}),
(t.prototype.onmessage = function (e) {
this.mSocket.onmessage = e;
}),
(t.prototype.onopen = function (e) {
this.mSocket.onopen = e;
}),
(t.prototype.onclose = function (e) {
this.mSocket.onclose = e;
}),
(t.prototype.send = function (e) {
this.mSocket.send(e);
}),
new t(o)
);
};
}
if ("object" == typeof weex)
try {
console.log("test webSocket for weex");
var o = weex.requireModule("webSocket");
return (
console.log("find webSocket for weex:" + o),
function (e) {
try {
o.close();
} catch (e) {}
return o.WebSocket(e, ""), o;
}
);
} catch (e) {
console.log(e);
}
if ("object" == typeof WebSocket)
return function (o) {
return new e(o);
};
throw new Error("the js environment do not support websocket");
}),
(SekiroClient.prototype.connect = function () {
console.log("sekiro: begin of connect to wsURL: " + this.wsURL);
var e = this;
try {
this.socket = this.webSocketFactory(this.wsURL);
} catch (o) {
return (
console.log("sekiro: create connection failed,reconnect after 2s:" + o),
void setTimeout(function () {
e.connect();
}, 2e3)
);
}
this.socket.onmessage(function (o) {
e.handleSekiroRequest(o.data);
}),
this.socket.onopen(function (e) {
console.log("sekiro: open a sekiro client connection");
}),
this.socket.onclose(function (o) {
console.log("sekiro: disconnected ,reconnection after 2s"),
setTimeout(function () {
e.connect();
}, 2e3);
});
}),
(SekiroClient.prototype.handleSekiroRequest = function (e) {
console.log("receive sekiro request: " + e);
var o = JSON.parse(e),
t = o.__sekiro_seq__;
if (o.action) {
var n = o.action;
if (this.handlers[n]) {
var s = this.handlers[n],
i = this;
try {
s(
o,
function (e) {
try {
i.sendSuccess(t, e);
} catch (e) {
i.sendFailed(t, "e:" + e);
}
},
function (e) {
i.sendFailed(t, e);
}
);
} catch (e) {
console.log("error: " + e), i.sendFailed(t, ":" + e);
}
} else this.sendFailed(t, "no action handler: " + n + " defined");
} else this.sendFailed(t, "need request param {action}");
}),
(SekiroClient.prototype.sendSuccess = function (e, o) {
var t;
if ("string" == typeof o)
try {
t = JSON.parse(o);
} catch (e) {
(t = {}).data = o;
}
else "object" == typeof o ? (t = o) : ((t = {}).data = o);
(Array.isArray(t) || "string" == typeof t) && (t = { data: t, code: 0 }),
t.code ? (t.code = 0) : (t.status, (t.status = 0)),
(t.__sekiro_seq__ = e);
var n = JSON.stringify(t);
console.log("response :" + n), this.socket.send(n);
}),
(SekiroClient.prototype.sendFailed = function (e, o) {
"string" != typeof o && (o = JSON.stringify(o));
var t = {};
(t.message = o), (t.status = -1), (t.__sekiro_seq__ = e);
var n = JSON.stringify(t);
console.log("sekiro: response :" + n), this.socket.send(n);
}),
(SekiroClient.prototype.registerAction = function (e, o) {
if ("string" != typeof e) throw new Error("an action must be string");
if ("function" != typeof o) throw new Error("a handler must be function");
return (
console.log("sekiro: register action: " + e), (this.handlers[e] = o), this
);
});
编写 sekiro 启动函数,其中需要注意的是:
- 您可以先使用测试服务
http://sekiro.iinti.cn/
登陆测试用户- 用户名:sekiro
- 密码:sekiro
function start_sekiro() {
// 根据ip和port进行配置,创建client
var client = new SekiroClient(
"ws://sekiro.iinti.cn:5612/business/register?group=demo-ws&clientId=" +
Math.random()
); // 修改成自己的group
// 注册分组
client.registerAction("testAction", function (request, resolve, reject) {
var param = request["param"]; // 接收传递的参数
if (!param) {
reject("need param{param}");
return;
}
console.log(`testAction:${param}`);
try {
var result = document.cookie; // 获取页面cookie
resolve(result); // 将cookie传递出去
} catch (e) {
reject(`error:${e}`); // 异常处理
}
});
}
最后,在浏览器刷新目标网站页面,让油猴脚本生效 打开控制台可以看到顺利建立了连接~
完整代码如下:
// ==UserScript==
// @name sekiro-test
// @namespace http://tampermonkey.net/
// @version 2024-01-13
// @description try to take over the world!
// @author You
// @match https://*
// @icon https://www.google.com/s2/favicons?sz=64&domain=xiaohongshu.com
// @grant none
// ==/UserScript==
(function () {
// 引入关键函数
function SekiroClient(e) {
if (((this.wsURL = e), (this.handlers = {}), (this.socket = {}), !e))
throw new Error("wsURL can not be empty!!");
(this.webSocketFactory = this.resolveWebSocketFactory()), this.connect();
}
(SekiroClient.prototype.resolveWebSocketFactory = function () {
if ("object" == typeof window) {
var e = window.WebSocket ? window.WebSocket : window.MozWebSocket;
return function (o) {
function t(o) {
this.mSocket = new e(o);
}
return (
(t.prototype.close = function () {
this.mSocket.close();
}),
(t.prototype.onmessage = function (e) {
this.mSocket.onmessage = e;
}),
(t.prototype.onopen = function (e) {
this.mSocket.onopen = e;
}),
(t.prototype.onclose = function (e) {
this.mSocket.onclose = e;
}),
(t.prototype.send = function (e) {
this.mSocket.send(e);
}),
new t(o)
);
};
}
if ("object" == typeof weex)
try {
console.log("test webSocket for weex");
var o = weex.requireModule("webSocket");
return (
console.log("find webSocket for weex:" + o),
function (e) {
try {
o.close();
} catch (e) {}
return o.WebSocket(e, ""), o;
}
);
} catch (e) {
console.log(e);
}
if ("object" == typeof WebSocket)
return function (o) {
return new e(o);
};
throw new Error("the js environment do not support websocket");
}),
(SekiroClient.prototype.connect = function () {
console.log("sekiro: begin of connect to wsURL: " + this.wsURL);
var e = this;
try {
this.socket = this.webSocketFactory(this.wsURL);
} catch (o) {
return (
console.log(
"sekiro: create connection failed,reconnect after 2s:" + o
),
void setTimeout(function () {
e.connect();
}, 2e3)
);
}
this.socket.onmessage(function (o) {
e.handleSekiroRequest(o.data);
}),
this.socket.onopen(function (e) {
console.log("sekiro: open a sekiro client connection");
}),
this.socket.onclose(function (o) {
console.log("sekiro: disconnected ,reconnection after 2s"),
setTimeout(function () {
e.connect();
}, 2e3);
});
}),
(SekiroClient.prototype.handleSekiroRequest = function (e) {
console.log("receive sekiro request: " + e);
var o = JSON.parse(e),
t = o.__sekiro_seq__;
if (o.action) {
var n = o.action;
if (this.handlers[n]) {
var s = this.handlers[n],
i = this;
try {
s(
o,
function (e) {
try {
i.sendSuccess(t, e);
} catch (e) {
i.sendFailed(t, "e:" + e);
}
},
function (e) {
i.sendFailed(t, e);
}
);
} catch (e) {
console.log("error: " + e), i.sendFailed(t, ":" + e);
}
} else this.sendFailed(t, "no action handler: " + n + " defined");
} else this.sendFailed(t, "need request param {action}");
}),
(SekiroClient.prototype.sendSuccess = function (e, o) {
var t;
if ("string" == typeof o)
try {
t = JSON.parse(o);
} catch (e) {
(t = {}).data = o;
}
else "object" == typeof o ? (t = o) : ((t = {}).data = o);
(Array.isArray(t) || "string" == typeof t) && (t = { data: t, code: 0 }),
t.code ? (t.code = 0) : (t.status, (t.status = 0)),
(t.__sekiro_seq__ = e);
var n = JSON.stringify(t);
console.log("response :" + n), this.socket.send(n);
}),
(SekiroClient.prototype.sendFailed = function (e, o) {
"string" != typeof o && (o = JSON.stringify(o));
var t = {};
(t.message = o), (t.status = -1), (t.__sekiro_seq__ = e);
var n = JSON.stringify(t);
console.log("sekiro: response :" + n), this.socket.send(n);
}),
(SekiroClient.prototype.registerAction = function (e, o) {
if ("string" != typeof e) throw new Error("an action must be string");
if ("function" != typeof o) throw new Error("a handler must be function");
return (
console.log("sekiro: register action: " + e),
(this.handlers[e] = o),
this
);
});
function start_sekiro() {
// 根据ip和port进行配置,创建client
var client = new SekiroClient(
"ws://sekiro.iinti.cn:5612/business/register?group=demo-ws&clientId=" +
Math.random()
); // 修改成自己的group
// 注册分组
client.registerAction("testAction", function (request, resolve, reject) {
var param = request["param"]; // 接收传递的参数
if (!param) {
reject("need param{param}");
return;
}
console.log(`testAction:${param}`);
try {
var result = document.cookie; // 获取页面cookie
resolve(result); // 将cookie传递出去
} catch (e) {
reject(`error:${e}`); // 异常处理
}
});
}
setTimeout(start_sekiro, 2000); // 等待20s加载Sekiro客户端
})();
验证
在浏览器地址栏使用 get 请求进行验证:
https://sekiro.iinti.cn/business/invoke?group=demo-ws&action=testAction¶m=testparm
可以看到成功返回了我们的 cookie(油猴脚本中注册的 testAction 的逻辑
Sekiro 文档 && 测试账户登陆
文档地址:https://sekiro.iinti.cn/sekiro-doc/
登陆站点:http://sekiro.iinti.cn/
- 测试账户用户名:sekiro
- 密码:sekiro
用户在登陆后可以建立自己的分组
查看 group 级别监控、action 级别监控、客户端监控等