diff --git a/packages/libs/lib-server/src/index.ts b/packages/libs/lib-server/src/index.ts index a6d3f603..f4bfaf59 100644 --- a/packages/libs/lib-server/src/index.ts +++ b/packages/libs/lib-server/src/index.ts @@ -1,8 +1,9 @@ import { SysSettingsEntity } from './system/index.js'; import { AccessEntity } from './user/access/entity/access.js'; +import { AddonEntity } from "./user/index.js"; export * from './basic/index.js'; export * from './system/index.js'; export * from './user/index.js'; export { LibServerConfiguration as Configuration } from './configuration.js'; -export const libServerEntities = [SysSettingsEntity, AccessEntity]; +export const libServerEntities = [SysSettingsEntity, AccessEntity,AddonEntity]; diff --git a/packages/libs/lib-server/src/system/settings/service/models.ts b/packages/libs/lib-server/src/system/settings/service/models.ts index 08431bbd..05391a60 100644 --- a/packages/libs/lib-server/src/system/settings/service/models.ts +++ b/packages/libs/lib-server/src/system/settings/service/models.ts @@ -36,6 +36,7 @@ export class SysPublicSettings extends BaseSettings { captchaEnabled = false; //验证码类型 captchaType?: string; + captchaAddonId?:string; } export class SysPrivateSettings extends BaseSettings { @@ -50,9 +51,6 @@ export class SysPrivateSettings extends BaseSettings { dnsResultOrder? = ''; commonCnameEnabled?: boolean = true; - //验证码配置id - captchaAddonId?: number; - sms?: { type?: string; config?: any; diff --git a/packages/libs/lib-server/src/user/addon/entity/addon.ts b/packages/libs/lib-server/src/user/addon/entity/addon.ts index f62de283..4d16fb43 100644 --- a/packages/libs/lib-server/src/user/addon/entity/addon.ts +++ b/packages/libs/lib-server/src/user/addon/entity/addon.ts @@ -12,7 +12,7 @@ export class AddonEntity { name: string; - @Column({ comment: 'addon类型', length: 100 }) + @Column({ name: 'addon_type', comment: 'addon类型', length: 100 }) addonType: string; diff --git a/packages/libs/lib-server/src/user/addon/service/addon-service.ts b/packages/libs/lib-server/src/user/addon/service/addon-service.ts index f4834c27..a4a9ba7d 100644 --- a/packages/libs/lib-server/src/user/addon/service/addon-service.ts +++ b/packages/libs/lib-server/src/user/addon/service/addon-service.ts @@ -39,6 +39,11 @@ export class AddonService extends BaseService { throw new ValidateException('您无权查看该Addon配置'); } } + if (!param.userId){ + param.isSystem = true + }else{ + param.isSystem = false + } delete param._copyFrom return await super.add(param); } @@ -65,6 +70,8 @@ export class AddonService extends BaseService { id: entity.id, name: entity.name, userId: entity.userId, + addonType: entity.addonType, + type: entity.type, }; } @@ -197,7 +204,7 @@ export class AddonService extends BaseService { const addonDefine = this.getDefineByType( type,addonType) - const defaultConfig = await this.getDefault(userId); + const defaultConfig = await this.getDefault(userId,addonType); if (defaultConfig) { return defaultConfig; } diff --git a/packages/ui/certd-client/src/locales/langs/en-US/certd.ts b/packages/ui/certd-client/src/locales/langs/en-US/certd.ts index 19e35501..fd0809ed 100644 --- a/packages/ui/certd-client/src/locales/langs/en-US/certd.ts +++ b/packages/ui/certd-client/src/locales/langs/en-US/certd.ts @@ -711,6 +711,10 @@ export default { setting: { showRunStrategy: "Show RunStrategy", showRunStrategyHelper: "Allow modify the run strategy of the task", + + captchaEnabled: "Enable Captcha", + captchaHelper: "Whether to enable captcha verification for login", + captchaType: "Captcha Type", }, }, modal: { @@ -731,4 +735,8 @@ export default { challengeSetting: "Challenge Setting", gotoCnameTip: "Please go to CNAME Record Page", }, + addonSelector: { + select: "Select", + placeholder: "select please", + }, }; diff --git a/packages/ui/certd-client/src/locales/langs/zh-CN/certd.ts b/packages/ui/certd-client/src/locales/langs/zh-CN/certd.ts index a2966391..65e40373 100644 --- a/packages/ui/certd-client/src/locales/langs/zh-CN/certd.ts +++ b/packages/ui/certd-client/src/locales/langs/zh-CN/certd.ts @@ -714,6 +714,10 @@ export default { setting: { showRunStrategy: "显示运行策略选择", showRunStrategyHelper: "任务设置中是否允许选择运行策略", + + captchaEnabled: "启用验证码", + captchaHelper: "登录时是否启用验证码", + captchaType: "验证码类型", }, }, modal: { @@ -734,4 +738,8 @@ export default { challengeSetting: "校验配置", gotoCnameTip: "CNAME域名配置请前往CNAME记录页面添加", }, + addonSelector: { + select: "选择", + placeholder: "请选择", + }, }; diff --git a/packages/ui/certd-client/src/views/certd/addon/addon-selector/index.vue b/packages/ui/certd-client/src/views/certd/addon/addon-selector/index.vue new file mode 100644 index 00000000..595c0a08 --- /dev/null +++ b/packages/ui/certd-client/src/views/certd/addon/addon-selector/index.vue @@ -0,0 +1,173 @@ + + + + diff --git a/packages/ui/certd-client/src/views/certd/addon/api.ts b/packages/ui/certd-client/src/views/certd/addon/api.ts index 818a49c1..f3004e82 100644 --- a/packages/ui/certd-client/src/views/certd/addon/api.ts +++ b/packages/ui/certd-client/src/views/certd/addon/api.ts @@ -1,14 +1,23 @@ import { request } from "/src/api/service"; import { RequestHandleReq } from "/@/components/plugins/lib"; -export function createAddonApi() { - const apiPrefix = "/addon"; +export function createAddonApi(opts: { from: any; addonType: string }) { + let apiPrefix = "/addon"; + if (opts.from === "sys") { + apiPrefix = "/sys/addon"; + } return { async GetList(query: any) { return await request({ url: apiPrefix + "/page", method: "post", - data: query, + data: { + ...query, + query: { + addonType: opts.addonType, + ...query.query, + }, + }, }); }, @@ -16,7 +25,10 @@ export function createAddonApi() { return await request({ url: apiPrefix + "/add", method: "post", - data: obj, + data: { + ...obj, + addonType: opts.addonType, + }, }); }, @@ -46,7 +58,7 @@ export function createAddonApi() { async GetOptions(id: number) { return await request({ - url: apiPrefix + "/options", + url: apiPrefix + `/options?addonType=${opts.addonType}`, method: "post", }); }, @@ -68,22 +80,22 @@ export function createAddonApi() { async GetSimpleInfo(id: number) { return await request({ - url: apiPrefix + "/simpleInfo", + url: apiPrefix + `/simpleInfo?addonType=${opts.addonType}`, method: "post", params: { id }, }); }, - async GetDefineTypes(addonType: string) { + async GetDefineTypes() { return await request({ - url: apiPrefix + `/getTypeDict?addonType=${addonType}`, + url: apiPrefix + `/getTypeDict?addonType=${opts.addonType}`, method: "post", }); }, async GetProviderDefine(type: string) { return await request({ - url: apiPrefix + "/define", + url: apiPrefix + `/define?addonType=${opts.addonType}`, method: "post", params: { type }, }); @@ -91,14 +103,14 @@ export function createAddonApi() { async GetProviderDefineByType(type: string) { return await request({ - url: apiPrefix + "/defineByType", + url: apiPrefix + `/defineByType?addonType=${opts.addonType}`, method: "post", params: { type }, }); }, async Handle(req: RequestHandleReq, opts: any = {}) { - const url = `/pi/handle/${req.type}`; + const url = `/handle/${req.type}?addonType=${opts.addonType}`; const { typeName, action, data, input } = req; const res = await request({ url, diff --git a/packages/ui/certd-client/src/views/certd/addon/common.tsx b/packages/ui/certd-client/src/views/certd/addon/common.tsx index 7d123a3b..9a9e9805 100644 --- a/packages/ui/certd-client/src/views/certd/addon/common.tsx +++ b/packages/ui/certd-client/src/views/certd/addon/common.tsx @@ -5,6 +5,7 @@ import { forEach, get, merge, set } from "lodash-es"; import { Modal } from "ant-design-vue"; import { mitter } from "/@/utils/util.mitt"; import { useI18n } from "/src/locales"; +import * as pipelineApi from "/@/views/certd/pipeline/api"; export function addonProvide(api: any) { provide("addonApi", api); @@ -13,13 +14,13 @@ export function addonProvide(api: any) { }); } -export function getCommonColumnDefine(crudExpose: any, typeRef: any, api: any) { +export function getCommonColumnDefine(crudExpose: any, typeRef: any, api: any, addonType: string) { const { t } = useI18n(); - const addonTypeTypeDictRef = dict({ - data: [{ value: "captcha", label: "验证码" }], - }); + // const addonTypeTypeDictRef = dict({ + // data: [{ value: "captcha", label: "验证码" }], + // }); const addonTypeDictRef = dict({ - url: "/addon/getTypeDict?addonType=captcha", + url: `/addon/getTypeDict?addonType=${addonType}`, }); const defaultPluginConfig = { component: { @@ -61,7 +62,6 @@ export function getCommonColumnDefine(crudExpose: any, typeRef: any, api: any) { } //字段配置赋值 columnsRef.value[key] = column; - console.log("form", columnsRef.value, form); }); } @@ -79,30 +79,30 @@ export function getCommonColumnDefine(crudExpose: any, typeRef: any, api: any) { show: false, }, }, - addonType: { - title: "Addon类型", - type: "dict-select", - dict: addonTypeTypeDictRef, - search: { - show: false, - }, - column: { - width: 200, - component: { - color: "auto", - }, - }, - form: { - onChange(ctx: { value: any }) { - addonTypeDictRef.url = `/addon/getTypeDict?addonType=${ctx.value}`; - }, - }, - editForm: { - component: { - disabled: false, - }, - }, - }, + // addonType: { + // title: "Addon类型", + // type: "dict-select", + // dict: addonTypeTypeDictRef, + // search: { + // show: false, + // }, + // column: { + // width: 200, + // component: { + // color: "auto", + // }, + // }, + // form: { + // onChange(ctx: { value: any }) { + // addonTypeDictRef.url = `/addon/getTypeDict?addonType=${ctx.value}`; + // }, + // }, + // editForm: { + // component: { + // disabled: false, + // }, + // }, + // }, type: { title: t("certd.notificationType"), type: "dict-select", diff --git a/packages/ui/certd-client/src/views/certd/addon/crud.tsx b/packages/ui/certd-client/src/views/certd/addon/crud.tsx index 5bc56a03..73f00f03 100644 --- a/packages/ui/certd-client/src/views/certd/addon/crud.tsx +++ b/packages/ui/certd-client/src/views/certd/addon/crud.tsx @@ -1,9 +1,10 @@ import { ref } from "vue"; import { getCommonColumnDefine } from "./common"; import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud"; -import { createAddonApi } from "/@/views/certd/addon/api"; -const api = createAddonApi(); + export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet { + const api = context.api; + const addonType = context.addonType; const pageRequest = async (query: UserPageQuery): Promise => { return await api.GetList(query); }; @@ -25,7 +26,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat }; const typeRef = ref(); - const commonColumnsDefine = getCommonColumnDefine(crudExpose, typeRef, api); + const commonColumnsDefine = getCommonColumnDefine(crudExpose, typeRef, api, addonType); return { crudOptions: { request: { diff --git a/packages/ui/certd-client/src/views/certd/addon/index.vue b/packages/ui/certd-client/src/views/certd/addon/index.vue index 059404bb..3b4607db 100644 --- a/packages/ui/certd-client/src/views/certd/addon/index.vue +++ b/packages/ui/certd-client/src/views/certd/addon/index.vue @@ -14,14 +14,14 @@ import { defineComponent, onActivated, onMounted } from "vue"; import { useFs } from "@fast-crud/fast-crud"; import createCrudOptions from "./crud"; -import { createNotificationApi } from "./api"; -import { notificationProvide } from "/@/views/certd/notification/common"; +import { createAddonApi } from "./api"; +import { addonProvide } from "/@/views/certd/addon/common"; export default defineComponent({ - name: "NotificationManager", + name: "AddonManager", setup() { - const api = createNotificationApi(); - notificationProvide(api); + const api = createAddonApi(); + addonProvide(api); const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions, context: { api } }); // 页面打开后获取列表数据 diff --git a/packages/ui/certd-client/src/views/framework/login/captcha-input.vue b/packages/ui/certd-client/src/views/framework/login/captcha-input.vue new file mode 100644 index 00000000..a910b8d4 --- /dev/null +++ b/packages/ui/certd-client/src/views/framework/login/captcha-input.vue @@ -0,0 +1,90 @@ + + + diff --git a/packages/ui/certd-client/src/views/framework/login/captcha.vue b/packages/ui/certd-client/src/views/framework/login/captcha.vue deleted file mode 100644 index 2d9d2fdd..00000000 --- a/packages/ui/certd-client/src/views/framework/login/captcha.vue +++ /dev/null @@ -1,46 +0,0 @@ - - diff --git a/packages/ui/certd-client/src/views/framework/login/index.vue b/packages/ui/certd-client/src/views/framework/login/index.vue index ff38ca56..8e5fd6e4 100644 --- a/packages/ui/certd-client/src/views/framework/login/index.vue +++ b/packages/ui/certd-client/src/views/framework/login/index.vue @@ -21,8 +21,8 @@ - - + + @@ -95,10 +95,10 @@ import ImageCode from "/@/views/framework/login/image-code.vue"; import SmsCode from "/@/views/framework/login/sms-code.vue"; import { useI18n } from "/@/locales"; import { LanguageToggle } from "/@/vben/layouts"; - +import CaptchaInput from "./captcha-input.vue"; export default defineComponent({ name: "LoginPage", - components: { LanguageToggle, SmsCode, ImageCode }, + components: { LanguageToggle, SmsCode, ImageCode, CaptchaInput }, setup() { const { t } = useI18n(); const verifyCodeInputRef = ref(); @@ -165,6 +165,10 @@ export default defineComponent({ const handleFinish = async (values: any) => { loading.value = true; try { + formState.captcha = await doCaptchaValidate(); + if (!formState.captcha) { + return; + } const loginType = formState.loginType; await userStore.login(loginType, toRaw(formState)); } catch (e: any) { @@ -199,6 +203,20 @@ export default defineComponent({ return sysPublicSettings.registerEnabled && (sysPublicSettings.usernameRegisterEnabled || sysPublicSettings.emailRegisterEnabled); } + const captchaInputRef = ref(); + async function doCaptchaValidate() { + if (!sysPublicSettings.captchaEnabled) { + return {}; + } + const res = await captchaInputRef.value.getValidatedForm(); + if (!res) { + return false; + } + return { + ...res, + }; + } + return { t, loading, @@ -216,6 +234,7 @@ export default defineComponent({ handleTwoFactorSubmit, verifyCodeInputRef, settingStore, + captchaInputRef, }; }, }); diff --git a/packages/ui/certd-client/src/views/sys/settings/tabs/base.vue b/packages/ui/certd-client/src/views/sys/settings/tabs/base.vue index a3024ae4..d574a755 100644 --- a/packages/ui/certd-client/src/views/sys/settings/tabs/base.vue +++ b/packages/ui/certd-client/src/views/sys/settings/tabs/base.vue @@ -47,6 +47,20 @@
+ + +
+
+ + + + + + + + {{ t("certd.saveButton") }} @@ -63,7 +77,7 @@ import { useSettingStore } from "/@/store/settings"; import { notification } from "ant-design-vue"; import { util } from "/@/utils"; import { useI18n } from "/src/locales"; - +import AddonSelector from "../../../certd/addon/addon-selector/index.vue"; const { t } = useI18n(); defineOptions({ @@ -115,6 +129,11 @@ async function stopOtherUserTimer() { }); } +function onAddonChanged(target: any) { + debugger; + formState.public.captchaType = target.type; +} + const testProxyLoading = ref(false); async function testProxy() { testProxyLoading.value = true; diff --git a/packages/ui/certd-server/db/migration/v10029__addon.sql b/packages/ui/certd-server/db/migration/v10029__addon.sql new file mode 100644 index 00000000..be7c3a95 --- /dev/null +++ b/packages/ui/certd-server/db/migration/v10029__addon.sql @@ -0,0 +1,13 @@ + +CREATE TABLE "cd_addon" ( + "id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, + "user_id" integer NOT NULL, + "name" varchar(100) NOT NULL, + "type" varchar(100) NOT NULL, + "addon_type" varchar(100) NOT NULL, + "is_default" boolean NOT NULL DEFAULT (false), + "is_system" boolean NOT NULL DEFAULT (false), + "setting" text, + "create_time" datetime NOT NULL DEFAULT (CURRENT_TIMESTAMP), + "update_time" datetime NOT NULL DEFAULT (CURRENT_TIMESTAMP) +); diff --git a/packages/ui/certd-server/src/controller/sys/addon/addon-controller.ts b/packages/ui/certd-server/src/controller/sys/addon/addon-controller.ts new file mode 100644 index 00000000..bd586423 --- /dev/null +++ b/packages/ui/certd-server/src/controller/sys/addon/addon-controller.ts @@ -0,0 +1,83 @@ +import { ALL, Body, Controller, Inject, Post, Provide, Query } from "@midwayjs/core"; +import { AddonRequestHandleReq, AddonService, Constants } from "@certd/lib-server"; +import { AddonController } from "../../user/addon/addon-controller.js"; + +@Provide() +@Controller('/api/sys/addon') +export class SysAddonController extends AddonController { + @Inject() + service2: AddonService; + + getService(): AddonService { + return this.service2; + } + + getUserId() { + // checkComm(); + return 0; + } + + @Post('/page', { summary: 'sys:settings:view' }) + async page(@Body(ALL) body: any) { + return await super.page(body); + } + + @Post('/list', { summary: 'sys:settings:view' }) + async list(@Body(ALL) body: any) { + return await super.list(body); + } + + @Post('/add', { summary: 'sys:settings:edit' }) + async add(@Body(ALL) bean: any) { + return await super.add(bean); + } + + @Post('/update', { summary: 'sys:settings:edit' }) + async update(@Body(ALL) bean: any) { + return await super.update(bean); + } + @Post('/info', { summary: 'sys:settings:view' }) + async info(@Query('id') id: number) { + return await super.info(id); + } + + @Post('/delete', { summary: 'sys:settings:edit' }) + async delete(@Query('id') id: number) { + return await super.delete(id); + } + @Post('/define', { summary: Constants.per.authOnly }) + async define(@Query('type') type: string,@Query('addonType') addonType: string) { + return await super.define(type,addonType); + } + + @Post('/getTypeDict', { summary: Constants.per.authOnly }) + async getTypeDict(@Query('addonType') addonType: string) { + return await super.getTypeDict(addonType); + } + + @Post('/simpleInfo', { summary: Constants.per.authOnly }) + async simpleInfo(@Query('addonType') addonType: string,@Query('id') id: number) { + return await super.simpleInfo(addonType,id); + } + + @Post('/getDefaultId', { summary: Constants.per.authOnly }) + async getDefaultId(@Query('addonType') addonType: string) { + return await super.getDefaultId(addonType); + } + + @Post('/setDefault', { summary: Constants.per.authOnly }) + async setDefault(@Query('addonType') addonType: string,@Query('id') id: number) { + return await super.setDefault(addonType,id); + } + + + @Post('/options', { summary: Constants.per.authOnly }) + async options(@Query('addonType') addonType: string) { + return await super.options(addonType); + } + + @Post('/handle', { summary: Constants.per.authOnly }) + async handle(@Body(ALL) body: AddonRequestHandleReq) { + return await super.handle(body); + } +} diff --git a/packages/ui/certd-server/src/controller/user/addon/addon-controller.ts b/packages/ui/certd-server/src/controller/user/addon/addon-controller.ts index de370ef4..299f7f5f 100644 --- a/packages/ui/certd-server/src/controller/user/addon/addon-controller.ts +++ b/packages/ui/certd-server/src/controller/user/addon/addon-controller.ts @@ -1,18 +1,17 @@ -import { ALL, Body, Controller, Inject, Post, Provide, Query } from '@midwayjs/core'; +import { ALL, Body, Controller, Inject, Post, Provide, Query } from "@midwayjs/core"; import { - AccessGetter, + AddonDefine, AddonRequestHandleReq, + AddonService, Constants, CrudController, newAddon, ValidateException } from "@certd/lib-server"; -import { AuthService } from '../../../modules/sys/authority/service/auth-service.js'; -import { checkPlus } from '@certd/plus-core'; -import { AddonService } from "@certd/lib-server"; -import { AddonDefine } from "@certd/lib-server"; -import { AccessRequestHandleReq, newAccess } from "@certd/pipeline"; +import { AuthService } from "../../../modules/sys/authority/service/auth-service.js"; +import { checkPlus } from "@certd/plus-core"; import { http, logger, utils } from "@certd/basic"; + /** * Addon */ diff --git a/packages/ui/certd-server/src/controller/user/login/login-controller.ts b/packages/ui/certd-server/src/controller/user/login/login-controller.ts index 7d2dfc33..f185f25e 100644 --- a/packages/ui/certd-server/src/controller/user/login/login-controller.ts +++ b/packages/ui/certd-server/src/controller/user/login/login-controller.ts @@ -1,8 +1,10 @@ -import { ALL, Body, Controller, Inject, Post, Provide } from '@midwayjs/core'; -import { LoginService } from '../../../modules/login/service/login-service.js'; -import { BaseController, Constants, SysPublicSettings, SysSettingsService } from '@certd/lib-server'; -import { CodeService } from '../../../modules/basic/service/code-service.js'; -import { checkComm } from '@certd/plus-core'; +import { ALL, Body, Controller, Inject, Post, Provide } from "@midwayjs/core"; +import { LoginService } from "../../../modules/login/service/login-service.js"; +import { AddonService, BaseController, Constants, SysPublicSettings, SysSettingsService } from "@certd/lib-server"; +import { CodeService } from "../../../modules/basic/service/code-service.js"; +import { checkComm } from "@certd/plus-core"; +import { logger } from "@certd/basic"; +import { ICaptchaAddon } from "../../../plugins/plugin-captcha/api.js"; /** */ @@ -16,14 +18,16 @@ export class LoginController extends BaseController { @Inject() sysSettingsService: SysSettingsService; + @Inject() + addonService: AddonService; @Post('/login', { summary: Constants.per.guest }) public async login( @Body(ALL) - user: any + body: any ) { - await this.loginService.doCaptchaValidate({form:user}) - const token = await this.loginService.loginByPassword(user); + await this.loginService.doCaptchaValidate({form:body.captcha}) + const token = await this.loginService.loginByPassword(body); this.writeTokenCookie(token); return this.ok(token); } @@ -79,4 +83,24 @@ export class LoginController extends BaseController { }); return this.ok(); } + + @Post('/captcha/getParams', { summary: Constants.per.guest }) + async getCaptchaParams() { + + const settings = await this.sysSettingsService.getPublicSettings() + if (settings.captchaEnabled) { + const addonId = settings.captchaAddonId; + + const addon:ICaptchaAddon = await this.addonService.getAddonById(addonId,true,0) + if (!addon) { + logger.warn('验证码插件还未配置') + return this.ok({}); + } + + const params = await addon.getClientParams() + return this.ok(params); + } + + return this.ok({}); + } } diff --git a/packages/ui/certd-server/src/modules/login/service/login-service.ts b/packages/ui/certd-server/src/modules/login/service/login-service.ts index fe02f93a..c6c29272 100644 --- a/packages/ui/certd-server/src/modules/login/service/login-service.ts +++ b/packages/ui/certd-server/src/modules/login/service/login-service.ts @@ -105,19 +105,21 @@ export class LoginService { const pubSetting = await this.sysSettingsService.getPublicSettings() if (pubSetting.captchaEnabled) { - const prvSetting = await this.sysSettingsService.getPrivateSettings() - const addon = await this.addonService.getById(prvSetting.captchaAddonId,0) + const addon = await this.addonService.getById(pubSetting.captchaAddonId,0) if (!addon) { logger.warn('验证码插件还未配置,忽略验证码校验') return true } - if (addon.addonType !== pubSetting.captchaType) { + if (addon.define.name !== pubSetting.captchaType) { logger.warn('验证码插件类型错误,忽略验证码校验') return true } - return await addon.onValidate(opts.form) + const res = await addon.onValidate(opts.form) + if (!res) { + throw new Error('验证码错误'); + } } return true diff --git a/packages/ui/certd-server/src/plugins/plugin-captcha/api.ts b/packages/ui/certd-server/src/plugins/plugin-captcha/api.ts new file mode 100644 index 00000000..1bfae9f4 --- /dev/null +++ b/packages/ui/certd-server/src/plugins/plugin-captcha/api.ts @@ -0,0 +1,4 @@ +export interface ICaptchaAddon{ + onValidate(data?:any):Promise; + getClientParams():Promise; +} diff --git a/packages/ui/certd-server/src/plugins/plugin-captcha/geetest/index.ts b/packages/ui/certd-server/src/plugins/plugin-captcha/geetest/index.ts index 033b4dae..1e1cb999 100644 --- a/packages/ui/certd-server/src/plugins/plugin-captcha/geetest/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-captcha/geetest/index.ts @@ -1,12 +1,13 @@ import { AddonInput, BaseAddon, IsAddon } from "@certd/lib-server/dist/user/addon/api/index.js"; import crypto from 'crypto'; +import { ICaptchaAddon } from "../api.js"; @IsAddon({ addonType:"captcha", name: 'geetest', title: '极验验证码', desc: '', }) -export class GeeTestCaptcha extends BaseAddon { +export class GeeTestCaptcha extends BaseAddon implements ICaptchaAddon{ @AddonInput({ title: 'captchaId', component: { @@ -43,6 +44,9 @@ export class GeeTestCaptcha extends BaseAddon { var captcha_output = data['captcha_output']; var pass_token = data['pass_token']; var gen_time = data['gen_time']; + if (!lot_number || !captcha_output || !pass_token || !gen_time) { + return false; + } // 生成签名, 使用标准的hmac算法,使用用户当前完成验证的流水号lot_number作为原始消息message,使用客户验证私钥作为key // 采用sha256散列算法将message和key进行单向散列生成最终的 “sign_token” 签名 @@ -78,8 +82,6 @@ export class GeeTestCaptcha extends BaseAddon { this.ctx.logger.error("极验验证服务异常",e) return true } - - } // 生成签名 @@ -102,7 +104,13 @@ export class GeeTestCaptcha extends BaseAddon { timeout: 5000 }; const result = await this.ctx.http.request(options); - return result.data; + return result; + } + + async getClientParams(): Promise { + return { + captchaId: this.captchaId, + } }