繁体   English   中英

“无效的 csrf 令牌”在 nodejs(Express) 中使用 CSURF。CSRF 令牌适用于第一个请求,但为所有其他请求提供错误

[英]"Invalid csrf token" using CSURF in nodejs(Express).CSRF token works fine for first request but give error for all other requests

我使用NodeJS Express 和passport.js 进行用户身份验证。 我在登录表单中实现了 csrf 身份验证。 第一次进入登录页面时,csrf 令牌工作正常,但是当我注销并重定向到登录页面时,我收到错误“无效的 csrf 令牌”。

我已经尝试使用 res.render({csrf: req.csrfToken()}); 将 csrf 令牌显式传递给视图(EJS 模板引擎); 但它不起作用。

const path = require('path');
const sequalize = require('./utils/database');
const localStrategy = require('passport-local').Strategy;
//const User = require('../models/user');
const bycrypt = require('bcryptjs');

const express = require('express');
const session = require('express-session');
const sessionStore = require('express-mysql-session')(session);
const passport = require('passport');
const bodyParser = require('body-parser');
const csrf = require('csurf');
const flash = require('connect-flash');
const User = require('./models/user');

const app = express();

var options = {
    host: 'localhost',
    port: 3306,
    user: 'root',
    password: '',
    database: 'lab'
};

var mysqlStore = new sessionStore(options);

app.set('view engine', 'ejs');
app.set('views', 'views');
app.use(flash());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, 'public')));
app.use(session({
    key: 'session_cookie_name',
    secret: 'session_cookie_secret',
    store: mysqlStore,
    resave: false,
    saveUninitialized: false
}));

app.use(passport.initialize());
app.use(passport.session());

app.use(csrf());
app.use(flash());
app.use((req, res, next) => {
    //res.locals.isAuthenticated = req.session.isLoggedIn;
    passport.serializeUser(function(user, done) {
        done(null, user);
    });

    passport.deserializeUser(function(user, done) {
        done(null, user);
    });

    passport.use(new localStrategy((username, password, done) => {
        //console.log(username);
        User.findOne({ email: username })
            .then(user => {
                if (!user) {
                    req.flash('err', 'Invalid email or password.');
                    done(null, false);
                }
                bycrypt
                    .compare(password, user.password)
                    .then(doMatch => {
                        if (doMatch) {
                            // req.session.isLoggedIn = true;
                            // req.session.user = user;
                            //console.log('Success');
                            done(null, user);
                        } else {
                            req.flash('err', 'Invalid email or password.');
                            //console.log('not logged in');
                            done(null, false);
                        }
                    })
                    .catch(err => {
                        req.flash('err', 'Something did not go well.');
                        //console.log('not logged in');
                        done(null, false);
                    });
            });
    }));
    res.locals.csrfToken = req.csrfToken();
    next();
});
app.use('/', adminRoute);
sequalize
.sync()
.then(() => {
        app.listen(3000);
    })
    .catch(err => {
        console.log(err);
    });

注销路由代码

req.logOut();
    res.render('auth/login', {
        flashError: req.flash('err')
    });

注销按钮的 HTML 代码

<form id="my_form" method="post" action="/logout">
      <button onclick="document.getElementById('my_form').submit();"><i class="fa fa-power-off" style="color:#E27D60"><span> <b> Logout</b></span></i></button>
</form>

这是我在使用 req.logout() 注销后呈现登录页面时得到的错误。

ForbiddenError: invalid csrf token at csrf (K:\\Node LAB\\node_modules\\csurf\\index.js:112:19) at Layer.handle [as handle_request] (K:\\Node LAB\\node_modules\\express\\lib\\router\\layer .js:95:5) at trim_prefix (K:\\Node LAB\\node_modules\\express\\lib\\router\\index.js:317:13) 在 K:\\Node LAB\\node_modules\\express\\lib\\router\\index.js :284:7 在 Function.process_params (K:\\Node LAB\\node_modules\\express\\lib\\router\\index.js:335:12) 在下一个 (K:\\Node LAB\\node_modules\\express\\lib\\router\\index.js:335:12) js:275:10) 在 SessionStrategy.strategy.pass (K:\\Node LAB\\node_modules\\passport\\lib\\middleware\\authenticate.js:338:9) 在 K:\\Node LAB\\node_modules\\passport\\lib\\strategies\\ session.js:69:12 at pass (K:\\Node LAB\\node_modules\\passport\\lib\\authenticator.js:337:31) 在反序列化 (K:\\Node LAB\\node_modules\\passport\\lib\\authenticator.js:349) :7) at K:\\Node LAB\\app.js:140:9 at pass (K:\\Node LAB\\node_modules\\passport\\lib\\authenticator.js:357:9) at Authenticator.deserializeUser (K:\\Node LAB \\node_modules\\passport\\lib\\authenticator.js: 362:5) 在 SessionStrategy.authenticate (K:\\Node LAB\\node_modules\\passport\\lib\\strategies\\session.js:60:10) 尝试 (K:\\Node LAB\\node_modules\\passport\\lib\\middleware\\authenticate. js:361:16) at authentication (K:\\Node LAB\\node_modules\\passport\\lib\\middleware\\authenticate.js:362:7) at Layer.handle [as handle_request] (K:\\Node LAB\\node_modules\\express\\ lib\\router\\layer.js:95:5) at trim_prefix (K:\\Node LAB\\node_modules\\express\\lib\\router\\index.js:317:13) 在 K:\\Node LAB\\node_modules\\express\\lib\\ router\\index.js:284:7 at Function.process_params (K:\\Node LAB\\node_modules\\express\\lib\\router\\index.js:335:12) 在下一个 (K:\\Node LAB\\node_modules\\express\\lib \\router\\index.js:275:10) 在初始化 (K:\\Node LAB\\node_modules\\passport\\lib\\middleware\\initialize.js:53:5)

最后,我想出了问题所在。 问题是我忘记在我的注销表单中添加 csrf 令牌的隐藏字段,因为 CSRF 身份验证需要每个表单都有这个字段。

我之前的注销按钮代码:

<form id="my_form" method="post" action="/logout">
    <button onclick="document.getElementById('my_form').submit();"><i class="fa fa-power-off" style="color:#E27D60"><span> <b> Logout</b></span></i></button>
</form>

现在我已将其更正为:

<form id="my_form" method="post" action="/logout">
     <input type="hidden" name="_csrf" value="<%= csrfToken %>">
     <button onclick="document.getElementById('my_form').submit();"><i class="fa fa-power-off" style="color:#E27D60"><span> <b> Logout</b></span></i></button>
</form>

在登录表单中,隐藏的 csrf 字段已经包含在内,这就是它工作正常的原因

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM