Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions History.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
0.1.4.1 / 2017-11-09
==================

* Add Reset Captcha Example

0.1.4.0 / 2017-11-08
==================

* Update Readme with Options
* Add Letter Spacing Option


0.1.3 / 2017-04-21
==================

Expand Down
29 changes: 27 additions & 2 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,18 @@ app.get(captchaUrl, captcha.image())
app.get('/', (req, res) => {
res.type('html')
res.end(`
<img src="${ captchaUrl }"/>
<img id="image" src="${ captchaUrl }"/>
<form action="/login" method="post">
<a id="reset-button">Reset</a>
<input type="text" name="${ captchaFieldName }"/>
<input type="submit"/>
</form>
<script>
document.getElementById('reset-button').addEventListener('click',function(){
document.getElementById('image').setAttribute('src',"")
document.getElementById('image').setAttribute('src', '${ captchaUrl }')
})
</script>
`)
})

Expand All @@ -56,4 +63,22 @@ app.post('/login', (req, res) => {
app.listen(8080, () => {
console.log('server started')
})
```
```

## Options

- cookie = default('captcha')
- cryptoAlg = default('sha1')
- cryptoPass = default(crypto.randomBytes(32))
- color = default('rgb(0,100,100)')
- background = default('rgb(255,200,150)')
- lineWidth = default(8)
- fontSize = default(80)
- codeLength = default(6)
- canvasWidth = default(250)
- canvasHeight = default(150)
- letterSpacing = default(0.375)


var nodecaptcha = require('./captcha')
var captcha = nodecaptcha.create({ cookie: 'captcha',canvasHeight: 200,letterSpacing:10})
94 changes: 45 additions & 49 deletions captcha.js
Original file line number Diff line number Diff line change
@@ -1,73 +1,69 @@
'use strict'
'use strict';

const Canvas = require('canvas')
const crypto = require('crypto')
const Canvas = require('canvas');
const crypto = require('crypto');

class Captcha {
constructor(params) {
params.cookie = params.cookie || 'captcha'
params.cryptoAlg = params.cryptoAlg || 'sha1'
params.cryptoPass = params.cryptoPass || crypto.randomBytes(32)
params.color = params.color || 'rgb(0,100,100)'
params.background = params.background || 'rgb(255,200,150)'
params.lineWidth = params.lineWidth || 8
params.fontSize = params.fontSize || 80
params.codeLength = params.codeLength || 6
params.canvasWidth = params.canvasWidth || 250
params.canvasHeight = params.canvasHeight || 150

this.params = params
params.cookie = params.cookie || 'captcha';
params.cryptoAlg = params.cryptoAlg || 'sha1';
params.cryptoPass = params.cryptoPass || crypto.randomBytes(32);
params.color = params.color || 'rgb(0,100,100)';
params.background = params.background || 'rgb(255,200,150)';
params.lineWidth = params.lineWidth || 8;
params.fontSize = params.fontSize || 80;
params.codeLength = params.codeLength || 6;
params.canvasWidth = params.canvasWidth || 250;
params.canvasHeight = params.canvasHeight || 150;
params.letterSpacing = params.letterSpacing || 0.375;
this.params = params;
}

image() {
return (req, res, next) => {
const canvas = new Canvas(this.params.canvasWidth, this.params.canvasHeight)
const ctx = canvas.getContext('2d')
return (req, res) => {
const canvas = new Canvas(this.params.canvasWidth, this.params.canvasHeight);
const ctx = canvas.getContext('2d');

ctx.antialias = 'gray'
ctx.fillStyle = this.params.background
ctx.fillRect(0, 0, this.params.canvasWidth, this.params.canvasHeight)
ctx.fillStyle = this.params.color
ctx.lineWidth = this.params.lineWidth
ctx.strokeStyle = this.params.color
ctx.font = `${this.params.fontSize }px sans`
ctx.antialias = 'gray';
ctx.fillStyle = this.params.background;
ctx.fillRect(0, 0, this.params.canvasWidth, this.params.canvasHeight);
ctx.fillStyle = this.params.color;
ctx.lineWidth = this.params.lineWidth;
ctx.strokeStyle = this.params.color;
ctx.font = `${this.params.fontSize }px sans`;

// draw two curve lines:
for (var i = 0; i < 2; i++) {
ctx.moveTo(Math.floor(0.08 * this.params.canvasWidth), Math.random() * this.params.canvasHeight)
ctx.bezierCurveTo(Math.floor(0.32 * this.params.canvasWidth), Math.random() * this.params.canvasHeight, Math.floor(1.07 * this.params.canvasHeight), Math.random() * this.params.canvasHeight, Math.floor(0.92 * this.params.canvasWidth), Math.random() * this.params.canvasHeight)
ctx.stroke()
for (let i = 0; i < 2; i++) {
ctx.moveTo(Math.floor(0.08 * this.params.canvasWidth), Math.random() * this.params.canvasHeight);
ctx.bezierCurveTo(Math.floor(0.32 * this.params.canvasWidth), Math.random() * this.params.canvasHeight, Math.floor(1.07 * this.params.canvasHeight), Math.random() * this.params.canvasHeight, Math.floor(0.92 * this.params.canvasWidth), Math.random() * this.params.canvasHeight);
ctx.stroke();
}

// draw text:
const text = ('' + crypto.randomBytes(4).readUIntBE(0, 4)).substr(2, this.params.codeLength)
const text = ('' + crypto.randomBytes(4).readUIntBE(0, 4)).substr(2, this.params.codeLength);
text.split('').forEach((char, i) => {
ctx.setTransform(Math.random() * 0.5 + 1, Math.random() * 0.4, Math.random() * 0.4, Math.random() * 0.5 + 1, Math.floor(0.375 * this.params.fontSize) * i + Math.floor(0.25 * this.params.fontSize), Math.floor(1.25 * this.params.fontSize))
ctx.fillText(char, 0, 0)
})
ctx.setTransform(Math.random() * 0.5 + 1, Math.random() * 0.4, Math.random() * 0.4, Math.random() * 0.5 + 1, Math.floor(this.params.letterSpacing * this.params.fontSize) * i + Math.floor(0.25 * this.params.fontSize), Math.floor(1.25 * this.params.fontSize));
ctx.fillText(char, 0, 0);
});

// save text:
if (req.session === undefined) {
throw Error('node-captcha requires express-session!')
}
req.session[this.params.cookie] = text
if (req.session === undefined) throw Error('node-captcha requires express-session!');
req.session[this.params.cookie] = text;

// send image:
res.type('jpg')
res.header('Cache-Control', 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0')
res.header('Expires', 'Sun, 19 May 1984 02:00:00 GMT')
canvas.jpegStream().pipe(res)
}
res.type('jpg');
res.header('Cache-Control', 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0');
res.header('Expires', 'Sun, 19 May 1984 02:00:00 GMT');
canvas.jpegStream().pipe(res);
};
}

check(req, text) {
if (req.session === undefined) {
throw Error('node-captcha requires express-session!')
}
const res = req.session[this.params.cookie] === text
req.session[this.params.cookie] = null
return res
if (req.session === undefined) throw Error('node-captcha requires express-session!');
const res = req.session[this.params.cookie] === text;
req.session[this.params.cookie] = null;
return res;
}
}

module.exports.create = params => new Captcha(params)
module.exports.create = params => new Captcha(params);
Loading