【问题标题】:getting csrf working expressjs angularjs nginx让 csrf 工作 expressjs angularjs nginx
【发布时间】:2013-12-13 19:59:00
【问题描述】:

我在设置(理解?)csrf 保护时遇到问题。我的设置是 nginx 使用 expressjs 为 api 调用和 angularjs 前端提供静态文件。所有对 /api/* 的调用都发送到 express,其他任何事情都由 nginx 处理。

我的登录系统设置好并且工作正常(没有 csrf 保护)。我在这里使用了这个例子(http://mircozeiss.com/using-csrf-with-express-and-angular/),但我一直被 403 禁止。 (偶尔登录会起作用,直到我注销并重新登录)。

这是我的相关代码:

//nginx

server {
listen 80;
server_name login.example.dev;
root /home/example/www/login/pub;
index index.html;

location /api {
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header Host $proxy_host;
    proxy_pass_header X-XSRF-TOKEN;
    proxy_pass http://127.0.0.1:8000;
}

location / {
    if ($args ~ "_escaped_fragment_=(.*)") {
            rewrite ^ /snapshots/$1;
    }
    try_files snapshots$request_uri.html $uri /index.html;
}
}

//server.js

var config=require('./config.js');
var express = require('express');
var http = require('http');
var RedisStore=require('connect-redis')(express);
var member=require('./routes/member.js');
var auth=require('./routes/auth.js');
var app = express();

app.configure(function(){

    app.enable('trust proxy');
    app.set('port', process.env.PORT || config.app.port);
    app.use(express.bodyParser());
    app.use(express.methodOverride());
    app.use(express.cookieParser());
    app.use(express.session({
    proxy:true,
      secret: config.session.secret,
      store: new RedisStore({db:config.session.redis.db,prefix:config.session.redis.prefix}),
      key: config.session.key,
      cookie:{
        domain:config.session.domain,
        maxAge:config.session.maxAge
      }
    }));

    app.use(express.csrf());
    app.use(function(req, res, next) {
          res.cookie('XSRF-TOKEN', req.csrfToken(),{httpOnly:true,domain:'.example.dev'});
          next();
    });
    app.use(app.router);
});

app.get(config.app.prefix+'/member/get-data.json',restrict,member.getData);
app.post(config.app.prefix+'/auth/login',auth.login);
app.get(config.app.prefix+'/auth/logout', auth.logout);

http.createServer(app).listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});

function restrict(req,res,next){
        if(config.session.dataKey in req.session){
            var d=req.session[config.session.dataKey];
            req.session.regenerate(function(err){
                if(err){
                    console.log('Err regen session');
                }else{
                    req.session[config.session.dataKey]=d;
                    next();
                }
            });
        }else{
            req.session.destroy();
            res.json(401,{"msg":"not logged in."});
        }

}

//angularjs

var loginCtrl = lmu.controller('LoginCtrl',['$scope','$http','User','$location',
function($scope,$http,User,$l){

    $scope.cred={};


    $scope.login=function(){
        $http.post('/api/auth/login',$scope.cred).then(function(res){
                User.data=res.data;
                $l.path('/account');
        },function(e){
                User.data=e.data;
        });
    };

}]);

【问题讨论】:

    标签: angularjs nginx express csrf


    【解决方案1】:

    我也有同样的问题。您正在使用session.regenerate() 来销毁旧会话(我认为这是避免会话固定的好做法),但您也使用此调用破坏了 XSRF 令牌的秘密。 我首先尝试在session.regenerate() 的回调中设置 XSRF cookie,但这不起作用,因为不会再次创建秘密。

    您需要的是登录请求之后的 GET 请求。然后将生成一个新的 XSRF 机密,并在 cookie 中设置正确的令牌。

    并且您应该确保有 GET 请求通过 node.js,因为除了 HEAD、OPTIONS 和 GET 之外的所有 HTTP 方法都受 CSRF 保护。所以你不能在那里设置cookie。

    【讨论】:

    • 感谢您的提示。我会再搞砸一点,让你知道它是怎么回事。
    猜你喜欢
    • 2016-09-24
    • 2014-05-13
    • 2017-10-29
    • 1970-01-01
    • 2020-12-18
    • 1970-01-01
    • 2023-03-18
    • 2013-11-03
    • 2016-12-21
    相关资源
    最近更新 更多