2013-11-27 66 views
0

我有麻煩設置(理解?)csrf保護。我的設置是nginx爲express調用靜態文件提供api調用和angularjs前端。所有對/ api/*的調用都將被髮送以表示,其他任何內容均由nginx處理。越來越csrf工作expressjs angularjs 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; 
     }); 
    }; 

}]);

回答

0

我有同樣的問題。您正在使用session.regenerate()來銷燬舊會話(我認爲這是避免會話固定的好習慣),但是您也會使用此調用破壞XSRF令牌的祕密。 我首先嚐試在回調session.regenerate()中設置XSRF cookie,但這不起作用,因爲祕密不會再次創建。

您需要的是在登錄請求之後的GET請求。然後將生成一個新的XSRF祕密,並在cookie中設置正確的標記。

而且您應該確保有GET請求經過node.js,因爲除HEAD,OPTIONS和GET之外的所有HTTP方法均受CSRF保護。所以你不能在那裏設置一個cookie。

+0

感謝您的提示。我會更多地討論它,讓你知道它是如何發展的。 –