неверный токен csrf при использовании ajax - PullRequest
0 голосов
/ 26 февраля 2019

Я начал изучать NodeJs и под влиянием своих знаний о js я начинаю писать код для создания логики регистрации пользователя.

По сути, я настроил ExpressJS следующим образом:

const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const session = require('express-session');
const csrf = require('csurf');
const cookieParser = require('cookie-parser');

app.use(session({
    secret: 'foofofoo',
    resave: false,
    saveUninitialized: true,
    cookie: { secure: true }
}));

app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(csrf());
app.use(function (req, res, next) {
    var csrfToken = req.csrfToken();
    res.cookie('XSRF-TOKEN', csrfToken);
    res.locals.csrfToken = csrfToken;
    next();
});

затем я создал базовое .ejs представление для регистрации пользователя:

<meta name="csrf-token" content="<%= csrfToken %>">
<p>
    <label class="w3-text-blue"><b>User Name</b></label>
    <input class="w3-input w3-border" id="uname" name="uname" type="text"></p>
<p>
    <label class="w3-text-blue"><b>Password</b></label>
    <input class="w3-input w3-border" id="upass" name="pass" type="text"></p>
<p>
    <button class="w3-btn w3-blue" id="regForm">Register</button></p>

csrfToken взято middleware выше.Когда пользователь нажимает кнопку regForm, этот код вызывается:

$("#regForm").click(function () {
    let uname = $("#uname").val();
    let upass = $("#upass").val();
    let token  = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
    let regData = 
    {
        'name': uname, 
        'pass': upass 
    };

    $.ajax({
        type: 'POST',
        url: '/registerUser',
        headers: {"X-CSRF-Token": token },
        data: regData,
        success: function (data) {
            $("#mainDiv").html(data);
        }
    });
});

и, глядя на запрос ajax, токен передается правильно:

enter image description here

но внутри консоли я получаю:

ForbiddenError: неверный токен csrf

это метод маршрута:

app.post('/registerUser', function(req, res, next){
    //todo
});

Ответы [ 2 ]

0 голосов
/ 13 марта 2019

Прежде всего, спасибо вам, так как вы начали работать над nodejs и пробовали эти вещи самостоятельно.

Нет необходимости изменять структуру или сам код, так как он написан правильно.Есть только одна ошибка, которая вызывает проблему, и это в вашей csrf инициализации.Пожалуйста, добавьте параметр cookie в инициализацию csrf , как показано ниже:

app.use(csrf({ cookie: true }));

Кроме того, всегда используйте хранилище сеансов в своем приложении.Ниже приведен пример использования экспресс-сессии в качестве хранилища сеансов:

var session        = require('express-session');
var MemoryStore    = require('session-memory-store')(session);

app.use(session({
    store : new MemoryStore({ expires : 86400, checkperiod : 1800}),
    secret: 'foofofoo',
    resave: false,
    saveUninitialized: true,
    cookie: { secure: true }
}));
0 голосов
/ 13 марта 2019

Из документов csurf :

Внутри представления установите значение csrfToken в качестве значения скрытого поля ввода с именем _csrf

Сначала измените это:

<meta name="csrf-token" content="<%= csrfToken %>">

на следующее:

<input type="hidden" name="_csrf" value="<%= csrfToken %>" id="csrf">

Затем на своей странице jQuery измените это:

let token  = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
{
    'name': uname, 
    'pass': upass 
};

на следующее:

let token  = $('#csrf').val();
{
    'name': uname, 
    'pass': upass,
    '_csrf':token
};

Если у вас все еще есть проблемы, дайте мне знать, что происходит, когда вы пытаетесь это сделать.

PS: этот вопрос был довольно хорошим справочным материалом для вашей проблемы.

...