Nodejs验证码解决方案求助

Nodejs验证码解决方案求助

###目前实现 目前使用的是gm模块,在每次请求时新生成一张验证码图片

###存在缺陷

  1. 每次请求都生成,效率低,不抗并发
  2. 由于imagemagick生成的图片没有输出到内存的输出流,每次都保存到本地,需要定期清理,不然硬盘会爆

###需求 抗并发、模式识别不出验证码、解决磁盘清理问题。

7 回复

当然可以。为了满足你的需求,我们可以考虑使用一个内存中存储验证码图像的方案,并且使用更高效的验证码生成库。这里推荐使用 canvasnode-canvas-captcha 库来生成验证码图像,这样可以避免频繁地读写磁盘,提高并发处理能力。

示例代码

首先,你需要安装必要的依赖:

npm install canvas node-canvas-captcha

接下来,你可以创建一个简单的服务器来处理验证码生成和验证:

const express = require('express');
const { createCanvas, registerFont } = require('canvas');
const captcha = require('node-canvas-captcha');

registerFont('./fonts/arial.ttf', { family: 'Arial' });

const app = express();
app.use(express.json());

// 存储验证码数据
let captchaData = {};

// 生成并返回验证码
app.get('/captcha', (req, res) => {
    const captchaObj = captcha.create();
    const captchaText = captchaObj.text;

    // 将验证码文本存储在内存中
    captchaData[captchaText] = captchaObj.data;

    // 将验证码图像作为响应返回
    res.writeHead(200, {
        'Content-Type': 'image/png',
    });
    res.end(captchaObj.data);
});

// 验证验证码
app.post('/validate-captcha', (req, res) => {
    const { text, captchaId } = req.body;
    if (captchaData[captchaId] && captchaData[captchaId].text === text) {
        res.send({ success: true });
    } else {
        res.send({ success: false });
    }
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
    console.log(`Server is running on port ${PORT}`);
});

解释

  1. 安装依赖:

    • canvas: 用于生成验证码图像。
    • node-canvas-captcha: 用于方便地生成验证码图像。
  2. 注册字体:

    • 使用 registerFont 注册自定义字体(如果需要的话)。
  3. 生成验证码:

    • /captcha 路由生成一个新的验证码,并将验证码图像直接发送给客户端。
    • 验证码文本和图像数据被存储在内存中的 captchaData 对象里。
  4. 验证验证码:

    • /validate-captcha 路由接收用户输入的验证码文本,并与内存中的数据进行比较。
  5. 启动服务器:

    • 服务器监听指定端口,等待请求。

通过这种方式,我们避免了频繁地读写磁盘,并且提高了并发处理能力。验证码生成后存储在内存中,减少了磁盘清理的需求。


缓存静态图片,不错

而且目前的方案都需要安装一大堆依赖,Windows布署很不方便……

放静态文件的话容易被爬走。。==#验证码库要是被爬走了。。前端直接用文件匹配通过验证,相当于跳过验证码了。

这个看过,CentOS6.4下没装好==#。就没仔细研究。。要是效率够快的话可以试试看。。我再捣鼓捣鼓。。

这个和node无关,用任何服务器语言都能行。既然需要抗负载,那就建立一个服务来来提供服务。建立一个验证码池,池子缺省1000个,如果不足一千,就让服务器慢慢的生成。业务每次使用一个验证码,就消费一个,用完就删出文件。

Nodejs验证码解决方案求助

目前实现

目前使用的是gm模块,在每次请求时新生成一张验证码图片。

存在缺陷

  1. 每次请求都生成,效率低,不抗并发。
  2. 由于imagemagick生成的图片没有输出到内存的输出流,每次都保存到本地,需要定期清理,不然硬盘会爆。

需求

  • 抗并发
  • 解决模式识别不出验证码的问题
  • 解决磁盘清理问题

解决方案

为了提高并发处理能力和减少磁盘操作,我们可以使用内存缓存来存储验证码图像。此外,可以利用canvas库生成验证码图片,并直接在内存中处理。这样可以避免频繁地读写磁盘,从而提升性能和可靠性。

以下是一个简单的示例代码:

const express = require('express');
const { createCanvas, loadImage } = require('canvas');
const QRCode = require('qrcode');

const app = express();
const port = 3000;

const captchaCache = {};

// 生成验证码
function generateCaptcha() {
    const canvas = createCanvas(200, 100);
    const ctx = canvas.getContext('2d');

    // 设置背景颜色
    ctx.fillStyle = 'white';
    ctx.fillRect(0, 0, 200, 100);

    // 设置字体和文本
    ctx.font = '48px Arial';
    ctx.fillStyle = 'black';
    ctx.textAlign = 'center';

    // 生成随机字符串
    const captchaText = Math.random().toString(36).substr(2, 6);
    
    // 将验证码文本绘制到canvas上
    ctx.fillText(captchaText, 100, 70);

    return { text: captchaText, buffer: canvas.toBuffer('image/png') };
}

// 请求验证码接口
app.get('/captcha', (req, res) => {
    const captcha = generateCaptcha();

    // 缓存验证码
    captchaCache[captcha.text] = captcha.buffer;

    // 返回验证码图片
    res.set('Content-Type', 'image/png');
    res.send(captcha.buffer);
});

// 验证验证码接口
app.post('/verify-captcha', (req, res) => {
    const { captchaText, userCaptcha } = req.body;
    
    if (captchaCache[captchaText] && captchaCache[captchaText].toString('base64') === userCaptcha) {
        res.json({ success: true });
    } else {
        res.json({ success: false });
    }
});

app.listen(port, () => {
    console.log(`Server running at http://localhost:${port}`);
});

代码解释

  1. generateCaptcha 函数:使用 canvas 库生成一个验证码图片,并将其转换为 buffer
  2. /captcha 路由:生成验证码并缓存到内存中,然后返回验证码图片。
  3. /verify-captcha 路由:验证用户提交的验证码是否正确。

这种方式不仅减少了磁盘操作,还提高了并发处理能力,同时也解决了模式识别不出验证码的问题。

回到顶部