Ошибка при попытке объединить Passport JS и ReCAPTCHA V2. «SyntaxError: JSON .parse: неожиданный символ в строке 1 столбца 1 данных JSON» - PullRequest
0 голосов
/ 02 марта 2020

Настройка моей первой ExpressJS страницы портфолио с логинами пользователей с использованием Passport JS. Я хотел добавить ReCAPTCHA V2 от Google в процесс входа в систему, но я получаю сообщение об ошибке при объединении Passport и ReCAPTCHA.

Ошибка: SyntaxError: JSON .parse: неожиданный символ в строке 1 столбец 1 JSON данных

Я считаю, что ошибка связана с тем, как я настроил return next () в моем разделе POST, но я не могу понять, почему. Я пробовал несколько разных конфигураций, и поиск в Google не дал результатов.

Если я удаляю код паспорта JS в разделе POST, код ReCAPTCHA V2 работает. Я, конечно, упускаю что-то простое, но теряюсь, как заставить их работать вместе. Любая помощь приветствуется.

ПРИМЕЧАНИЕ: Я удалил два ключа ReCAPTCHA V2 для обеспечения безопасности (ключ сайта и секретный ключ), их нужно будет заменить на рабочие ключи от Google ReCAPTCHA версия 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")
});

my HTML file:

<!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>

Чтобы увидеть, что он работает без ошибок, удалите код passport.authenticate в разделе POST и возврат next () над ним. Также раскомментируйте возвращаемую рез. json строку успеха над следующей ().

...