chore: format

This commit is contained in:
xiaojunnuo
2026-05-31 01:41:33 +08:00
parent acd440106b
commit 4b57a0d729
557 changed files with 12530 additions and 14039 deletions
@@ -1,7 +1,7 @@
export type CaptchaRequest = {
remoteIp: string,
}
export interface ICaptchaAddon{
onValidate(data?:any,req?:CaptchaRequest):Promise<any>;
getCaptcha():Promise<any>;
remoteIp: string;
};
export interface ICaptchaAddon {
onValidate(data?: any, req?: CaptchaRequest): Promise<any>;
getCaptcha(): Promise<any>;
}
@@ -9,7 +9,6 @@ import { CaptchaRequest, ICaptchaAddon } from "../api.js";
showTest: false,
})
export class CfTurnstileCaptcha extends BaseAddon implements ICaptchaAddon {
@AddonInput({
title: "站点密钥",
component: {
@@ -37,30 +36,28 @@ export class CfTurnstileCaptcha extends BaseAddon implements ICaptchaAddon {
const { remoteIp } = req;
const formData = new FormData();
formData.append('secret', this.secretKey);
formData.append('response', token);
formData.append('remoteip', remoteIp);
formData.append("secret", this.secretKey);
formData.append("response", token);
formData.append("remoteip", remoteIp);
const res = await this.http.request({
url: 'https://challenges.cloudflare.com/turnstile/v0/siteverify',
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data',
},
data: formData
})
if (res.success) {
// Token is valid - process the form
return true;
} else {
// Token is invalid - reject the submission
const errorMessage = 'Cloudflare Turnstile 校验失败:' + res['error-codes'].join(', ')
this.logger.error(errorMessage);
throw new Error(errorMessage);
}
const res = await this.http.request({
url: "https://challenges.cloudflare.com/turnstile/v0/siteverify",
method: "POST",
headers: {
"Content-Type": "multipart/form-data",
},
data: formData,
});
if (res.success) {
// Token is valid - process the form
return true;
} else {
// Token is invalid - reject the submission
const errorMessage = "Cloudflare Turnstile 校验失败:" + res["error-codes"].join(", ");
this.logger.error(errorMessage);
throw new Error(errorMessage);
}
}
async getCaptcha(): Promise<any> {
@@ -3,53 +3,50 @@ import crypto from "crypto";
import { ICaptchaAddon } from "../api.js";
@IsAddon({
addonType:"captcha",
name: 'geetest',
title: '极验验证码v4',
desc: '',
showTest:false,
addonType: "captcha",
name: "geetest",
title: "极验验证码v4",
desc: "",
showTest: false,
})
export class GeeTestCaptcha extends BaseAddon implements ICaptchaAddon{
export class GeeTestCaptcha extends BaseAddon implements ICaptchaAddon {
@AddonInput({
title: '验证ID',
title: "验证ID",
component: {
placeholder: 'captchaId',
placeholder: "captchaId",
},
helper:"[极验验证码v4](https://console.geetest.com/sensbot/management) -> 创建业务模块 -> 新增业务场景",
helper: "[极验验证码v4](https://console.geetest.com/sensbot/management) -> 创建业务模块 -> 新增业务场景",
required: true,
})
captchaId = '';
captchaId = "";
@AddonInput({
title: '验证Key',
title: "验证Key",
component: {
placeholder: 'captchaKey',
placeholder: "captchaKey",
},
required: true,
})
captchaKey = '';
captchaKey = "";
async onValidate(data?:any) {
async onValidate(data?: any) {
if (!data) {
return false
return false;
}
// geetest 服务地址
// geetest server url
// geetest server url
const API_SERVER = "http://gcaptcha4.geetest.com";
// geetest 验证接口
// geetest server interface
// geetest 验证接口
// geetest server interface
const API_URL = API_SERVER + "/validate" + "?captcha_id=" + this.captchaId;
// 前端参数
// web parameter
var lot_number = data['lot_number'];
var captcha_output = data['captcha_output'];
var pass_token = data['pass_token'];
var gen_time = data['gen_time'];
const lot_number = data["lot_number"];
const captcha_output = data["captcha_output"];
const pass_token = data["pass_token"];
const gen_time = data["gen_time"];
if (!lot_number || !captcha_output || !pass_token || !gen_time) {
return false;
}
@@ -57,23 +54,23 @@ export class GeeTestCaptcha extends BaseAddon implements ICaptchaAddon{
// 生成签名, 使用标准的hmac算法,使用用户当前完成验证的流水号lot_number作为原始消息message,使用客户验证私钥作为key
// 采用sha256散列算法将message和key进行单向散列生成最终的 “sign_token” 签名
// use lot_number + CAPTCHA_KEY, generate the signature
var sign_token = this.hmac_sha256_encode(lot_number, this.captchaKey);
const sign_token = this.hmac_sha256_encode(lot_number, this.captchaKey);
// 向极验转发前端数据 + “sign_token” 签名
// send web parameter and “sign_token” to geetest server
var datas = {
'lot_number': lot_number,
'captcha_output': captcha_output,
'pass_token': pass_token,
'gen_time': gen_time,
'sign_token': sign_token
const datas = {
lot_number: lot_number,
captcha_output: captcha_output,
pass_token: pass_token,
gen_time: gen_time,
sign_token: sign_token,
};
// post request
// 根据极验返回的用户验证状态, 网站主进行自己的业务逻辑
// According to the user authentication status returned by the geetest, the website owner carries out his own business logic
try{
const res = await this.doRequest(datas, API_URL)
try {
const res = await this.doRequest(datas, API_URL);
if (res.result == "success") {
// 验证成功
// verification successful
@@ -81,42 +78,38 @@ export class GeeTestCaptcha extends BaseAddon implements ICaptchaAddon{
} else {
// 验证失败
// verification failed
this.logger.error("极验验证不通过 ",res.reason)
this.logger.error("极验验证不通过 ", res.reason);
return false;
}
}catch (e) {
this.ctx.logger.error("极验验证服务异常",e)
return true
} catch (e) {
this.ctx.logger.error("极验验证服务异常", e);
return true;
}
}
// 生成签名
// Generate signature
hmac_sha256_encode(value, key){
var hash = crypto.createHmac("sha256", key)
.update(value, 'utf8')
.digest('hex');
// Generate signature
hmac_sha256_encode(value, key) {
const hash = crypto.createHmac("sha256", key).update(value, "utf8").digest("hex");
return hash;
}
// 发送post请求, 响应json数据如:{"result": "success", "reason": "", "captcha_args": {}}
// Send a post request and respond to JSON data, such as: {result ":" success "," reason ":" "," captcha_args ": {}}
async doRequest(datas, url){
var options = {
// 发送post请求, 响应json数据如:{"result": "success", "reason": "", "captcha_args": {}}
// Send a post request and respond to JSON data, such as: {result ":" success "," reason ":" "," captcha_args ": {}}
async doRequest(datas, url) {
const options = {
url: url,
method: "POST",
params: datas,
timeout: 5000
timeout: 5000,
};
const result = await this.ctx.http.request(options);
return result;
}
async getCaptcha(): Promise<any> {
async getCaptcha(): Promise<any> {
return {
captchaId: this.captchaId,
}
};
}
}
@@ -4,53 +4,52 @@ import { cache } from "@certd/basic";
import { nanoid } from "nanoid";
@IsAddon({
addonType:"captcha",
name: 'image',
title: '图片验证码',
desc: '',
showTest:false,
addonType: "captcha",
name: "image",
title: "图片验证码",
desc: "",
showTest: false,
})
export class ImageCaptcha extends BaseAddon implements ICaptchaAddon{
async onValidate(data?:any) {
export class ImageCaptcha extends BaseAddon implements ICaptchaAddon {
async onValidate(data?: any) {
if (!data) {
return false;
}
return await this.checkCaptcha(data.randomStr, data.imageCode)
return await this.checkCaptcha(data.randomStr, data.imageCode);
}
async getCaptchaText(randomStr:string) {
return cache.get('imgCode:' + randomStr);
async getCaptchaText(randomStr: string) {
return cache.get("imgCode:" + randomStr);
}
async removeCaptcha(randomStr:string) {
cache.delete('imgCode:' + randomStr);
async removeCaptcha(randomStr: string) {
cache.delete("imgCode:" + randomStr);
}
async checkCaptcha(randomStr: string, userCaptcha: string) {
const code = await this.getCaptchaText(randomStr);
if (code == null) {
throw new Error('验证码已过期');
throw new Error("验证码已过期");
}
if (code.toLowerCase() !== userCaptcha?.toLowerCase()) {
throw new Error('验证码不正确');
throw new Error("验证码不正确");
}
await this.removeCaptcha(randomStr);
return true;
}
async getCaptcha(): Promise<any> {
const svgCaptcha = await import('svg-captcha');
const c = svgCaptcha.create();
//{data: '<svg.../svg>', text: 'abcd'}
const imgCode = c.text; // = RandomUtil.randomStr(4, true);
const randomStr = nanoid(10)
cache.set('imgCode:' + randomStr, imgCode, {
ttl: 2 * 60 * 1000, //过期时间 2分钟
})
return {
randomStr: randomStr,
imageData: c.data,
}
}
async getCaptcha(): Promise<any> {
const svgCaptcha = await import("svg-captcha");
const c = svgCaptcha.create();
//{data: '<svg.../svg>', text: 'abcd'}
const imgCode = c.text; // = RandomUtil.randomStr(4, true);
const randomStr = nanoid(10);
cache.set("imgCode:" + randomStr, imgCode, {
ttl: 2 * 60 * 1000, //过期时间 2分钟
});
return {
randomStr: randomStr,
imageData: c.data,
};
}
}
@@ -1,4 +1,4 @@
export * from './geetest/index.js';
export * from './image/index.js';
export * from './tencent/index.js';
export * from './cf-turnstile/index.js';
export * from "./geetest/index.js";
export * from "./image/index.js";
export * from "./tencent/index.js";
export * from "./cf-turnstile/index.js";
@@ -94,7 +94,7 @@ export class TencentCaptcha extends BaseAddon implements ICaptchaAddon {
this.logger.error("腾讯云验证码账户欠费,临时放行:", err.message);
return true;
}
throw err
throw err;
}
}