干掉图形验证码!基于PoW的Cap验证码集成指南

B站影视 内地电影 2025-08-31 20:12 1

摘要:A modern, lightning-quick PoW captcha一种现代的、闪电般快速的工作量证明验证码Cap is a lightweight, modern open-source CAPTCHA alternative using proof-

A modern, lightning-quick PoW captcha

一种现代的、闪电般快速的工作量证明验证码

Cap is a lightweight, modern open-source CAPTCHA alternative using proof-of-work

Cap 是一款轻量级、现代化的开源验证码替代方案,采用工作量证明机制。

与传统验证码不同,Cap:

速度快且不干扰用户不使用跟踪技术或 cookie使用工作量证明而非干扰性谜题完全可访问且可自行托管

Cap 主要由小部件(可以以不可见的方式使用)和服务器(你也可以使用独立服务器)组成。另外,它还支持机器对机器通信,并且有一个类似于 Cloudflare 的检查点中间件。

#技术分享文档地址:capjs.js.org/

github:github.com/tiagorangel…

以在 Vue3 + ElementPlus 中使用为例

在 index.html 引入 Cap widget:

生产环境请引入固定版本

在 ElForm 中使用组件:

其中 data-cap-api-endpoint 为服务端验证 URL 我这里设置为:

const capApi = ref(`${import.meta.env.VITE_API_URL}/admin/sys/login/`);

data-cap-i18n 开头的几个选项为国际化设置。

设置表单,以及校验规则:

import { type FormInstance, type FormRules } from "element-plus";const formRef = ref;let formData = reactive({> username: "",> password: "",> code: "",> });const rules = reactive>({ username: [{ required: true, message: "请输入用户名" }], password: [{ required: true, message: "请输入密码" }], code: [{ required: true, message: "请点击验证" }], });

监听 Cap 校验结果:

onMounted( => { const widget = document.querySelector("#cap");widget?.addEventListener("solve", function (e: any) { formData.code = e.detail.token; }); });

表单校验及提交不在赘述

npm i @cap.js/server

在 Service 中创建 Cap 实例:

import { InjectRepository } from "@nestjs/typeorm";import Cap from "@cap.js/server";@Injectable export class LoginService { cap: Cap = new Cap({ tokens_store_path: ".data/tokensList.json" }); }

Cap 默认使用内存和文件存储 token,你可以将 noFSState 设置为 true ,仅使用内存存储 token。

你可以将此与设置 config.state 结合使用,以使用诸如 Redis 之类来存储令牌。

可以参考这个 Pull requests 。

在 Controller 中创建接口:

import { BadRequestException, Body, Controller, Post } from "@nestjs/common";import { LoginService } from "./login.service";@Controller("login") export class LoginController { constructor(private readonly loginService: LoginService) {}@Post("/challenge") async challenge { return this.loginService.cap.createChallenge; }@Post("/redeem") async redeem( @Body body: { token: string; solutions: Array } ) { const { token, solutions } = body; if (!token || !solutions) { return new BadRequestException("人机验证失败"); } return this.loginService.cap.redeemChallenge({ token, solutions }); } }

当用户点击客户端 Cap 组件时,将请求 /challenge 和 /redeem 获取 token。

最后在登录接口的 Service 内添加 token 验证:

const result = await this.cap.validateToken(loginDto.code);if (!result.success) { throw new BadRequestException("人机验证失败");}

如果你想看这篇文章内的详细代码,可以查看 foolon admin 的登录功能:

github:github.com/LLcci/foolo…

gitee:gitee.com/shangchehan…

如果你有任何想法,欢迎在评论区交流呀~

来源:墨码行者

相关推荐