javascript - 尝试结合 PassportJS 和 ReCAPTCHA V2 时出错。“SyntaxError:JSON.parse:JSON 数据第 1 行第 1 列的意外字符”
问题描述
设置我的第一个 ExpressJS 投资组合页面,用户使用 PassportJS 登录。我想将来自 Google 的 ReCAPTCHA V2 添加到登录过程中,但是当我结合 Passport 和 ReCAPTCHA 时出现错误。
错误:SyntaxError:JSON.parse:JSON 数据的第 1 行第 1 列出现意外字符
我相信错误来自我在 POST 部分中设置 return next() 的方式,但我不知道为什么。我尝试了一些不同的配置,谷歌搜索无济于事。
如果我删除 POST 部分中的 passportJS 代码,则 ReCAPTCHA V2 代码有效。我肯定错过了一些简单的东西,但我不知道如何让它们一起工作。任何帮助表示赞赏。
注意:为了安全起见,我删除了我的两个 ReCAPTCHA V2密钥(站点密钥和密钥),它们必须被 Google ReCAPTCHA Version 2中的工作密钥替换。
const express = require('express');
const bodyParser = require('body-parser');
const request = require('request');
const passport = require('passport');
const mongoose = require('mongoose');
const LocalStrategy = require('passport-local').Strategy;
const app = express();
mongoose.connect('mongodb://localhost/MyDatabase', { useNewUrlParser: true, useUnifiedTopology: true });
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(passport.initialize());
app.use(passport.session());
passport.use(new LocalStrategy(
function (username, password, done) {
UserDetails.findOne({
username: username
}, function (err, user) {
if (err) {
return done(err);
}
if (!user) {
return done(null, false);
}
if (user.password != password) {
return done(null, false);
}
return done(null, user);
});
}
));
passport.serializeUser(function (user, cb) {
cb(null, user.id);
});
passport.deserializeUser(function (id, cb) {
User.findById(id, function (err, user) {
cb(err, user);
});
});
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
const Schema = mongoose.Schema;
const UserDetail = new Schema({
username: String,
password: String
});
const UserDetails = mongoose.model('userInfo', UserDetail, 'userInfo');
app.post('/', (req, res) => {
if (
req.body.captcha === undefined ||
req.body.captcha === '' ||
req.body.captcha === null
) {
return res.json({ "success": false, "msg": "Please select captcha" }); // If no CAPTCHA is selected / checkbox not checked
}
// secret key
const secretKey = 'INSERT SECRET KEY'; // You need to add a secret key from Google ReCAPTCHA V2
// verify URL
const verifyUrl = `https://google.com/recaptcha/api/siteverify?secret=${secretKey}&response=${req.body.captcha}&remoteip=${req.connection.remoteAddress}`;
// make request to verify url
request(verifyUrl, (err, response, body) => {
body = JSON.parse(body);
console.log("parsed body: ", body);
// if not successful
if (body.success !== undefined && !body.success) {
console.log("Request verifyUrl failed");
return res.json({ "success": false, "msg": "Failed captcha vericiation" }); // if can't connect to Google and verify CAPTCHA
}
// line below works if passport code and next() is removed
// return res.json({ "success": true, "msg": "captcha passed!" }); // Connected to Google and verified CAPTCHA
});
return next(); // Is the error coming from this?
},
passport.authenticate('local'),
function (req, res) {
console.log("Passport function was called ...");
// If this function gets called, authentication was successful.
// `req.user` contains the authenticated user.
res.redirect('/success');
});
// ####################### PASSPORT
// ######################### PASSPORT END
app.listen(3000, () => {
console.log("SERVER STARTED on port 3000")
});
我的 HTML 文件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<script src="//www.google.com/recaptcha/api.js"></script>
<title>Recaptcha and Passport Test</title>
</head>
<body>
<div class="container">
<h1>Subscribe</h1>
<form id="subscribeForm">
<div class="form-group">
<label for="username">Username</label>
<input type="text" name="username" class="form-control" id="username">
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" name="password" class="form-control" id="password">
</div>
<div class="form-group">
<div class="g-recaptcha" data-sitekey="SITE KEY GOES HERE"></div>
</div>
<input type="submit" value="submit" class="btn btn-primary">
</form>
</div>
<script>
document.getElementById('subscribeForm').addEventListener('submit', submitForm);
function submitForm(e) {
e.preventDefault();
const username = document.querySelector('#username').value;
const password = document.querySelector('#password').value;
const captcha = document.querySelector('#g-recaptcha-response').value;
fetch('/', {
method: 'POST',
headers: {
'Accept': 'application/json, text/plain, */*',
'Content-type': 'application/json'
},
body: JSON.stringify({username: username, password: password, captcha: captcha})
})
.then((res) => res.json())
.then((data) => {
console.log("Fetch data: ", data);
})
}
</script>
</body>
</html>
要查看它运行时没有错误,请删除 POST 部分中的 passport.authenticate 代码,以及它上面的 return next()。还取消注释 next() 上方的 return res.json 成功行。
解决方案
推荐阅读
- swift - 如何创建大型 NSView/UIView 的“迷你地图”?
- sql - SQL - 为什么我需要转换为十进制?
- java - 我想遍历图像的数组列表
- c# - 在不适合屏幕的单元格中设置后,值会在不同的单元格中呈现
- ios - 从挂起状态唤醒后保持应用唤醒
- python - 使用列列表和值列表查询数据框
- python-3.x - 从文本文件中提取个人网站详细信息
- java - SimpleDateFormat 的不可解析日期异常
- javascript - 如何在 Firefox 和 Chrome 中阻止指定脚本
- excel - 在 Selenium VBA 中使用 Google Chrome(安装步骤)