使用AngularJS和Express的错误CSRF令牌

问题描述 投票:4回答:3

我想在我的应用程序中添加一个使用MEAN堆栈的CSRF保护。

我尝试过某人给出的答案:CSRF Protection in ExpressJS

但这是旧的快递版本,所以我做了一些改变:

app.use(cookieParser(config.cookieSecret, { httpOnly: true }));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(session({ secret: config.sessionSecret, resave: false, saveUninitialized: true }));
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
app.use(csrf({value: function(req) {
        var token = (req.body && req.body._csrf)
            || (req.query && req.query._csrf)
            || (req.headers['x-csrf-token'])
            || (req.headers['x-xsrf-token']);
        return token;
    }
}));
app.use(function(req, res, next) {
  res.cookie('XSRF-TOKEN', req.csrfToken());
  next();
});

我可以看到名为XSRF-TOKEN的令牌在我的应用上很好地生成(使用Chrome检查)。

但是当我发布一个表单(Angular frontend)时,我有一个关于令牌的错误:

{"message":"invalid csrf token","error":{"expose":true,"code":"EBADCSRFTOKEN","statusCode":403,"status":403}}

我错过了什么 ?我想知道req.csrfToken()是否会生成Angular给出的好令牌......

编辑:

我只是看到XSRF-TOKEN仅在$http请求中被AngularJS使用。所以我想我必须在我的表单中添加一个隐藏的输入来发布csrf值,由Express检查,但是如何?

angularjs cookies express csrf passport.js
3个回答
12
投票

最后我能够发送好的令牌值。这是完整的答案。

AngularJS在使用$http服务的请求期间使用CSRF保护(由Angular称为XSRF)。

执行XHR请求时,$ http服务从cookie(默认情况下为XSRF-TOKEN)读取令牌并将其设置为HTTP头(X-XSRF-TOKEN)。由于只有在您的域上运行的JavaScript才能读取Cookie,因此您的服务器可以确保XHR来自您域上运行的JavaScript。不会为跨域请求设置标头。

有很多帖子解释了如何使用ExpressJS 3.xx发送XSRF-TOKEN,但有些东西随4.xx版本而变化。 Connect中间件不再包括在内。 Express使用自己的middelware:cookie-parserbody-parserexpress-sessioncsurf

1 - 发送XSRF-TOKEN cookie

第一步是将cookie从后端发送到前端(Express to Angular):

var express         = require('express');
var app             = express();
var cookieParser    = require('cookie-parser');
var bodyParser      = require('body-parser');
var session         = require('express-session');
var config          = require('./lib/config'); //config.js file with hard-coded options.
var csrf            = require('csurf');

app.use(cookieParser(config.cookieSecret, { httpOnly: true }));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(session({ 
    name: 'sessionID', 
    secret: config.sessionSecret, 
    cookie: {
        path: '/',
        httpOnly: true,
        secure: false,
        maxAge: 3600000
    },
    rolling: true, 
    resave: false, 
    saveUninitialized: true 
}));
app.use(csrf());
app.use(function(req, res, next) {
    res.cookie('XSRF-TOKEN', req.csrfToken());
    next();
});

现在,Angular能够在$ http请求期间设置其HTTP标头(X-XSRF-TOKEN)。示例:

<body ng-app="testApp">
    <div ng-controller="LoginCtrl">
        <form role="form" ng-submit="login()" >
           <input type="email" ng-model="user.email" />
           <input type="password" ng-model="user.password" />
           <input type="submit" value="Log In" />
        </form>
        <p style="color:red">{{loginMsg}}</p>
    </div>
</body>

<script>
    var app = angular.module('testApp', ['ngResource']);
    app.controller('LoginCtrl', function ($scope, $http) {
        $scope.user = {};
        $scope.loginMsg = '';
        $scope.login = function () {
             $http.post('/login', $scope.user).success(function () {
                  $window.location.href='/profile';
             }).error(function () {
                  $scope.loginMsg = 'Wrong credentials, try again.';
             });
        };
    });
</script>

2 - 以非Angular形式添加_csrf输入

那是我的问题,我不知道如何添加这个输入。最后,我创建了一个名为$csrf的新Angular服务:

    app.factory('$csrf', function () {
        var cookies = document.cookie.split('; ');
        for (var i=0; i<cookies.length; i++) {
          var cookie = cookies[i].split('=');
          if(cookie[0].indexOf('XSRF-TOKEN') > -1) {
            return cookie[1];
          }
        }
        return 'none';
    });

我在Plunker上做了一个例子:http://plnkr.co/edit/G8oD0dDJQmjWaa6D0x3u

希望我的回答会有所帮助。


1
投票

如果有人得到“csurf配置错误”,试试这个:

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

0
投票

我已经创建了可以直接使用的存储库。

node

https://github.com/nil4you/node-csrf-and-http-only-cookie-with-spa

angular

https://github.com/nil4you/angular-csrf-and-httponly-cookie-demo

在这里问任何问题,因为我看不到很多编码问题,这都是关于正确的设置问题。

© www.soinside.com 2019 - 2024. All rights reserved.