I am trying to verify captcha by storing into a req.session
object.
The express server is running on 8181 and the client on 3000. But in the verify captcha req.session.captcha
is undefined. Please help me.
My server code:
var captchapng = require('captchapng');
var express = require('express');
var app = express();
var session = require('express-session');
var cookieParser = require('cookie-parser');
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
app.use(cookieParser());
app.use(session({
secret: 'abcd',
resave: false,
saveUninitialized: false,
cookie: {maxAge: 1000*60*60*24*30}, //30 days
}));
app.get('/captcha.png', function (request, response) {
if(request.url == '/captcha.png') {
var randNumber = Math.random()*9000+1000;
var p = new captchapng(80,30,parseInt(randNumber)); // width,height,numeric captcha
p.color(0, 0, 0, 0); // First color: background (red, green, blue, alpha)
p.color(80, 80, 80, 255); // Second color: paint (red, green, blue, alpha)
var no = parseInt(randNumber);
request.session.captcha = no.toString();
console.log(parseInt(randNumber));
console.log(request.session);
var img = p.getBase64();
var imgbase64 = new Buffer(img,'base64');
response.writeHead(200, {
'Content-Type': 'image/png'
});
response.end(imgbase64);
} else response.end('');
})
app.get('/verify-captcha', (req, res) => {
let captcha = req.query.captcha;
console.log(captcha, req.session);
if(req.session.captcha === Number(captcha)){
res.send({message:'verified'})
}
else
res.send({message: "Not Verified!"})
})
app.listen(8181);
My client code:
index.pug
extends layout
block content
h1= title
p Welcome to #{title}
#image
img(src="http://localhost:8181/captcha.png")
#verify
input(type="text" placeholder="Enter captcha to verify" id="captcha")
button(type="button") Submit
captcha.js
$(document).ready(function(){
$('button').click(function(e){
var captcha = $('#captcha').val();
alert(captcha)
$.ajax({
url: 'http://localhost:8181/verify-captcha?captcha='+captcha,
type:'GET',
success: function(data){
alert(data)
},
error: function(err) {
alert(err);
}
})
})
})
Looks like app.use(cookieParser());
is the problem...
From express-session documentation:
Since version 1.5.0, the cookie-parser middleware no longer needs to be used for this module to work. This module now directly reads and writes cookies on req/res. Using cookie-parser may result in issues if the secret is not the same between this module and cookie-parser.
Remove cookieParser
or use the same secret app.use(cookieParser('abcd'));
.
Also:
Your client code has a typo:
url: 'http://localhost:8181/verify-captch?captcha='+captcha,
should be
url: 'http://localhost:8181/verify-captcha?captcha='+captcha,
In you server code you are comparing String with Number, should be like this:
app.get('/verify-captcha', (req, res) => {
let captcha = req.query.captcha;
console.log(captcha, req.session);
if(req.session.captcha === captcha){ // removed Number() here
res.send({message:'verified'})
}
else
res.send({message: "Not Verified!"})
})
Edit:
Looks like for $.ajax
to send cookies you have to add
xhrFields: {
withCredentials: true
},
Final client code:
$(document).ready(function(){
$('button').click(function(e){
var captcha = $('#captcha').val();
alert(captcha)
$.ajax({
url: 'http://localhost:8181/verify-captcha?captcha='+captcha,
type:'GET',
xhrFields: {
withCredentials: true
},
success: function(data){
console.log(data)
},
error: function(err) {
console.error(err);
}
})
})
})
Working example: https://stackblitz.com/edit/js-y6dzda (note: requires server running on localhost:8181)
Seems you haven't set your session as it should, change lines as follows:
app.get('/captcha.png', function (request, response) {
var session = request.session; // add this
if(request.url == '/captcha.png') {
var randNumber = Math.random()*9000+1000;
var p = new captchapng(80,30,parseInt(randNumber)); // width,height,numeric captcha
p.color(0, 0, 0, 0); // First color: background (red, green, blue, alpha)
p.color(80, 80, 80, 255); // Second color: paint (red, green, blue, alpha)
var no = parseInt(randNumber);
session.captcha = no.toString(); //change this line
console.log(parseInt(randNumber));
console.log(session); // and change this
var img = p.getBase64();
var imgbase64 = new Buffer(img,'base64');
response.writeHead(200, {
'Content-Type': 'image/png'
});
response.end(imgbase64);
} else response.end('');
})
this should set the session, because you were assigning no.toString() to request.session.captcha which isn't yet set, what exists instead is request.session.
This is an older issue but I faced the exact same scenario today. Some hours of searching found this workaround.
My environment :
If there is a better way do let all know. Steps I tried and was not successful:
It all depends on the way you are planning the CAPTCHA (in this particular case) In my case - I'm using a sessionStore (part of request) that contains a list of all sessions from user perspective. Each try is considered as a session. For the login screen I always consider using the last - but each case could be different.
What I ended up doing is to iterate and pick the last item from the list and I did get the captcha data element.
var captchaFromUser = "";
if(req.sessionStore){
if(req.sessionStore.sessions){
var idKeys = Object.keys(req.sessionStore.sessions);
if(req.sessionStore.sessions[idKeys[idKeys.length-1]]){
captchaFromUser =
JSON.parse(req.sessionStore.sessions[idKeys[idKeys.length-1]]).captcha;
}
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.