svg-captcha
非常好用的图形验证码库,通过一些配置后返回 svg
,并且无需安装任何 C++
插件。
如何使用
const Controller = require('egg').Controller;
const svgCaptcha = require('svg-captcha');
class CaptchaController extends Controller {
getCaptcha() {
const captcha = svgCaptcha.create({
// 随机字符的数量
size: 4,
// 过滤掉一些不容易辨识的字符
ignoreChars: 'iIl10oO',
// 干扰线条的数量
noise: 6,
// 字符将会有随机颜色而不再是灰色
color: true,
});
// 通过create方法会返回一个对象,其中有两个属性
// text: 验证码的文本
// data: svg数据
// 在session中保存正确的验证码文本,将svg数据返回给客户端
this.ctx.session.captcha = captcha.text.toLowerCase();
this.ctx.type = 'image/svg+xml';
this.ctx.body = captcha.data;
}
}
module.exports = CaptchaController;
新建好 CaptchaController
后我们还需要配置路由
只需在 router.js
中添加
router.get('/captcha', controller.captcha.getCaptcha);
然后前端就可以请求接口获取到图形验证码
检测验证码是否正确
我们可以制作一个中间件来验证验证码是否正确
module.exports = () => async (ctx, next) => {
try {
// 从请求体中拿取验证码
const captcha = ctx.request.body.captcha.toLowerCase();
// 获取之前保存在session中正确的验证码文本
const sessionCaptcha = ctx.session.captcha;
// 去除session中的验证码文本
ctx.session.captcha = null;
// 比较用户输入和正确文本是否一致
if (sessionCaptcha !== captcha) {
ctx.app.error.throw(406, '验证码错误');
}
} catch (e) {
ctx.logger.error(e);
ctx.app.error.throw(406, '验证码错误');
}
await next();
};
添加路由
router.post(
'/api/xxx',
app.middleware.captcha(),
// 后续操作 比如验证账号密码是否正确等
);
图形验证中session的坑
首页我们先了解一下服务端session
的原理
当用户首次与Web服务器建立连接的时候,服务器会给用户分发一个 SessionID
作为标识。SessionID
是一个由24个字符组成的随机字符串。服务器就会在响应头中添加 Set-Cookie
,将这个SessionID
以cookie
的方式保存在浏览器中,接下来的每次请求时浏览器会携带这个ID
,这样服务器就能区分发起请求的是哪一个客户端,才能到拿到session
中保存的数据。
所以想要session
正常使用,非常关键的一点就是cookie
能够携带在请求中。而现在前端常用的 axios
、fetch
默认都不会处理cookie
,例如在axios
中我们需要配置
// 全局配置,任何请求都允许cookie
axios.defaults.withCredentials = true;
// 也可以在指定的请求中允许cookie
服务器cors
也需要允许cookie
(在config.default.js
中配置)
exports.cors = { //解决跨域访问
// 允许跨域的方法
allowMethods: 'GET,HEAD,PUT,POST,DELETE,PATCH,OPTIONS',
// 允许携带cookie
credentials: true,
// 允许跨域的地址,不能为 '*',需指定一个地址
origin: 'xxx'
};