node-canvas实现登陆验证码

Posted by yuk on 2016-04-15

想给登陆加一个验证码验证的功能。

一:ccap

比较多的是推荐使用ccap。使用很简单。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const ccap = require('ccap')();
home.get('/home', (ctx, next) => {
return next().then(() => {
ctx.body = ctx.session.captcha;
});
});
home.get('/captcha', (ctx, next) => {
return next().then(() => {
let ary = ccap.get();
let txt = ary[0];
let buf = ary[1];
ctx.body = buf;
ctx.type = 'image/png';
ctx.session.captcha = txt;
});
});

然而最大的问题是,目前这个库会在文件夹下产生一堆临时文件,每天凌晨2点才回定时清理。我有一点强迫症。

二:koa-captcha

这个插件是koa中间件,原理是用canvas绘制

1
2
3
4
5
6
7
8
9
10
app.use(captcha({
url: '/captcha', // interface url
length: 5, //code length
fontSize: 6, //code size
width: 250, // captcha width
height: 150, // captcha height
color: 'rgb(0,0,0)', // code color,
background: 'rgb(255,255,255)', // captcha background color
lineWidth: 1 // Interference lines width
}))

美中不足就是中间件的方式. 我想把它放在控制器里调用,返回图片内容。

三:改造koa-captcha源码

因为原来是中间件的方式,查看代码只需要将最后返回的部分改成返回数据,而不是执行next;
原来的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
this.type = 'jpg'
this.set({
'Cache-Control': 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0',
'Expires': 'Sun, 12 Jan 1986 12:00:00 GMT'
})
this.session && (this.session.captcha = text)
this.body = yield new Promise(function(resolve, reject) {
canvas.toBuffer(function(err, data) {
if (err) {
reject(err)
} else {
resolve(data)
}
})
})
yield next

修改后的代码

1
2
3
4
5
6
7
8
9
10
return yield new Promise(function(resolve, reject) {
canvas.toBuffer(function(err, data) {

if (err) {
reject(err)
} else {
resolve([text,data])
}
})
});

四:验证部分

验证码生成的时候会在session保存验证码,提交登陆表单的时候验证session是否正确

1
2
3
4
5
6
7
8
9
login: function*(){
var params = this.request.body;
if(params.captcha !== this.session.captcha){
this.body = {
login: false,
msg: '验证码错误'
};
}
//...继续验证账号密码,也可以吧前面的验证写成路由中间件拦截,一样.