node.js - 无效的 CSRF token 错误 (express.js)

标签 node.js express angular csrf x-xsrf-token

我正在使用 node 6.5.0npm 3.10.3

当我尝试让用户登录网站时,收到此无效的 csrf token 错误。

{ ForbiddenError:无效的 csrf token 在csrf(/Users/Documents/web-new/node_modules/csurf/index.js:113:19)

在 redis 中存储 session 的登录无需 csurf 模块 ( https://github.com/expressjs/csurf )。使用 csurf 模块, session ID 存储在 redis 中,但我无法向客户端返回正确的响应以登录用户。我正在使用 Angular2 和 node/express。据我了解,Angular2 在使用 HTTP 服务时默认支持带有 CookieXSRFStrategy 的 CSRF/XSRF,所以我需要做的就是在 Node/express 端配置一些东西。带有 webpack-dev-server 的 Angular2 应用程序在 localhost:3000 上运行,而 Node/express 服务器在 localhost:3001 上运行。我支持 CORS。

我可以在 localhost:3000 的开发工具中看到名为 XSRF-TOKEN 的 cookie。

您能否建议我如何修复此错误?

//cors-middleware.js

var corsOptions = {
   origin: 'http://localhost:3000',
  credentials:true
}

app.use(cors(corsOptions));
app.use(function(req, res, next) {
    res.setHeader('Content-Type','application/json');
        next();
    })
};

//index.js

import path from 'path';
import session from 'express-session';
import connectRedis from 'connect-redis';
import rp from 'request-promise';
import * as _ from 'lodash';
import cors from 'cors';
import csurf from 'csurf';

const redisStore = connectRedis(session);
const dbStore = new redisStore(db);

let baseUrl = app.getValue('baseUrl');

/* ~~ api authentication ~~ */

let options = {
    method: 'POST',
    url: `${baseUrl}/authenticate`,
    rejectUnauthorized: false,
    qs: {
     username: 'someUsername', key: 'someKey'
    },
    json: true
};
rp(options)
    .then(response => {
        let apiToken = response.response;
        app.setValue("token", apiToken);
    })
    .catch(err => {
        console.error(err);
    });

/* ~~ configure session ~~ */

app.use(session({
    secret: app.getValue('env').SESSION_SECRET,
    store: dbStore,
    saveUninitialized: false,
    resave: false,
    rolling: true,
    cookie: {
        maxAge: 1000 * 60 * 30 // in milliseconds; 30 min
    }
}));

/* ~~ login user ~~ */

let csrf = csurf();

app.post('/loginUser', csrf, (req, res, next) => {
    let user = {};
    let loginOptions = {
        method: 'POST',
        url: `${baseUrl}/client/login`,
        rejectUnauthorized: false,
        qs: {
            token: app.getValue('token'),
            email: req.body.email,
            password: req.body.password
        },
        headers: {
            'Content-Type': 'application/json'
        },
        json: true
    };

    rp(loginOptions)
        .then(response => {
            let userToken = response.response.token;
            let clientId = response.response.clientId;

            req.session.key = req.session.id;

            user.userToken = userToken;
            user.clientId = clientId;


            let clientAttributeOptions = {
                url: `${baseUrl}/client/${clientId}/namevalue`,
                rejectUnauthorized: false,
                qs: {
                    token: app.getValue('token'),
                    usertoken: userToken
                },
                json: true
            };

            return rp(clientAttributeOptions);
        })
        .then(response => {
            req.session.user = user;
                res.send({user:user})
        })
        .catch(err => {
            next(err);
        })

});

最佳答案

我的问题是我仅将 csrf 函数作为中间件包含在 app.post('/loginUser) 中路线。

当我将它包含在所有 route 时,该模块工作正常。
let csrf = csurf(); app.get('/*', csrf, (req, res) => { res.sendFile(app.get('indexHTMLPath')); });

关于node.js - 无效的 CSRF token 错误 (express.js),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40848409/

相关文章:

node.js - 如何为winston@3记录器制作自定义json格式化程序?

node.js - Webpack 开发服务器 "before"功能

Angular 2 : How to handle app configuration for different environments

Angular 2 : using gzip files in production

Angular 2 Multi-Tenancy 系统 - 用户名为 "subdomain"

javascript - 然后在 Javascript 中使用外部变量

node.js - 跳过可选依赖项 : Unsupported platform for fsevents@1. 2.9:需要 {"os":"darwin","arch":"any"} (当前:{"os":"win32","arch"0 x104567910})

javascript - 用 Mongoose 枚举数组

node.js - 将字体添加到 Puppeteer PDF 渲染器

node.js - 使用express和passport未设置cookie