2014-10-28 2 views
15

Я новичок в angularJs и пытаюсь создать локальную аутентификацию для веб-сайта. Я прошел через различные источники, и это https://vickev.com/#!/article/authentication-in-single-page-applications-node-js-passportjs-angularjs было очень полезно. Когда я попытался построить то же самое в моем локальном хосте, мой код попал в цикл.NodeJs Passport isAuthenticated() возвращает false даже после входа в систему

app.post ('/ login', .....) возвращает пользователя в ответ, но после этого при загрузке страницы администратора он проверяет, вошел ли пользователь в систему, вызвав app.get ('/ loggedin ', ...) и req.isAuthenticated() возвращает false даже после входа в систему и переходит в цикл. я не могу понять, почему это происходит, PLZ помочь мне.

Server Side код

var express = require('express'); 
var http = require('http'); 
var path = require('path'); 
var passport = require('passport'); 
var LocalStrategy = require('passport-local').Strategy; 

//================================================================== 
// Define the strategy to be used by PassportJS 
passport.use(new LocalStrategy(
    function(username, password, done) { 
    if (username === "admin" && password === "admin") // stupid example 
     return done(null, {name: "admin"}); 

    return done(null, false, { message: 'Incorrect username.' }); 
    } 
)); 

// Serialized and deserialized methods when got from session 
passport.serializeUser(function(user, done) { 
    done(null, user); 
}); 

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

// Define a middleware function to be used for every secured routes 
var auth = function(req, res, next){ 
    if (!req.isAuthenticated()) 
    res.send(401); 
    else 
    next(); 
}; 
//================================================================== 

// Start express application 
var app = express(); 

// all environments 
app.set('port', process.env.PORT || 3000); 
app.use(express.favicon()); 
app.use(express.cookieParser()); 
app.use(express.bodyParser()); 
app.use(express.methodOverride()); 
app.use(express.session({ secret: 'securedsession' })); 
app.use(passport.initialize()); // Add passport initialization 
app.use(passport.session()); // Add passport initialization 
app.use(app.router); 

app.all('*', function(req, res, next) { 
    res.header("Access-Control-Allow-Origin", "*"); 
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); 
    next(); 
}); 

// development only 
if ('development' == app.get('env')) { 
    app.use(express.errorHandler()); 
} 

//================================================================== 
// routes 
app.get('/', function(req, res){ 
    res.render('index', { title: 'Express' }); 
}); 

app.get('/users', auth, function(req, res){ 
    res.send([{name: "user1"}, {name: "user2"}]); 
}); 
//================================================================== 

//================================================================== 
// route to test if the user is logged in or not 
app.get('/loggedin', function(req, res) { 
    res.send(req.isAuthenticated() ? req.user : '0'); 
}); 

// route to log in 
app.post('/login', passport.authenticate('local'), function(req, res) { 
    res.send(req.user); 
}); 

// route to log out 
app.post('/logout', function(req, res){ 
    req.logOut(); 
    res.send(200); 
}); 
//================================================================== 

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

Client Side Js файл

'use strict'; 

/********************************************************************** 
* Angular Application 
**********************************************************************/ 
var app = angular.module('app', ['ngResource','ngRoute']) 
    .config(function($routeProvider, $locationProvider, $httpProvider) { 
    //================================================ 
    // Check if the user is connected 
    //================================================ 
    var checkLoggedin = function($q, $timeout, $http, $location, $rootScope){ 
     // Initialize a new promise 
     var deferred = $q.defer(); 

     // Make an AJAX call to check if the user is logged in 
     $http.get('http://localhost:3000/loggedin').success(function(user){ 
     // Authenticated 
     if (user !== '0') 
      $timeout(deferred.resolve, 0); 

     // Not Authenticated 
     else { 
      $rootScope.message = 'You need to log in.'; 
      $timeout(function(){deferred.reject();}, 0); 
      $location.url('/login'); 
     } 
     }); 

     return deferred.promise; 
    }; 
    //================================================ 

    //================================================ 
    // Add an interceptor for AJAX errors 
    //================================================ 
    $httpProvider.responseInterceptors.push(function($q, $location) { 
     return function(promise) { 
     return promise.then(
      // Success: just return the response 
      function(response){ 
      return response; 
      }, 
      // Error: check the error status to get only the 401 
      function(response) { 
      if (response.status === 401) 
       $location.url('/login'); 
      return $q.reject(response); 
      } 
     ); 
     } 
    }); 
    //================================================ 

    //================================================ 
    // Define all the routes 
    //================================================ 
    $routeProvider 
     .when('/', { 
     templateUrl: 'views/main.html' 
     }) 
     .when('/admin', { 
     templateUrl: 'views/admin.html', 
     controller: 'AdminCtrl', 
     resolve: { 
      loggedin: checkLoggedin 
     } 
     }) 
     .when('/login', { 
     templateUrl: 'views/login.html', 
     controller: 'LoginCtrl' 
     }) 
     .otherwise({ 
     redirectTo: '/login' 
     }); 
    //================================================ 

    }) // end of config() 
    .run(function($rootScope, $http){ 
    $rootScope.message = ''; 

    // Logout function is available in any pages 
    $rootScope.logout = function(){ 
     $rootScope.message = 'Logged out.'; 
     $http.post('http://localhost:3000/logout'); 
    }; 
    }); 


/********************************************************************** 
* Login controller 
**********************************************************************/ 
app.controller('LoginCtrl', function($scope, $rootScope, $http, $location) { 
    // This object will be filled by the form 
    $scope.user = {}; 

    // Register the login() function 
    $scope.login = function(){ 
    $http.post('http://localhost:3000/login', { 
     username: $scope.user.username, 
     password: $scope.user.password, 
    }) 
    .success(function(user){ 
     // No error: authentication OK 
     $rootScope.message = 'Authentication successful!'; 
     $location.url('/admin'); 
    }) 
    .error(function(){ 
     // Error: authentication failed 
     $rootScope.message = 'Authentication failed.'; 
     $location.url('/login'); 
    }); 
    }; 
}); 



/********************************************************************** 
* Admin controller 
**********************************************************************/ 
app.controller('AdminCtrl', function($scope, $http) { 
    // List of users got from the server 
    $scope.users = []; 

    // Fill the array to display it in the page 
    $http.get('http://localhost:3000/users').success(function(users){ 
    for (var i in users) 
     $scope.users.push(users[i]); 
    }); 
}); 
+0

Эй! Я столкнулся с такой же проблемой, вы нашли основную причину? –

+0

Пример выглядит немного странно для меня, так как я ожидаю, что запрос '/ loggedin' будет подписан каким-то образом, по крайней мере, с' $ httpProvider.defaults.withCredentials = true; ', иначе я не уверен, что запрос будет содержат любую ссылку на зарегистрированного пользователя. – pasine

+0

быстрые мысли: >> угловая сессия = экспресс-сессия >>, когда угловая звонит «/» isloggedin он посылает это запрос сессии, чтобы выразить приложение, которое не аутентифицированым Добавление журналов и, если вы могли бы поделиться тем, будет полезно знать, что такое объект req и т. д., тогда мы могли бы, вероятно, решить эту проблему быстрее :) – drunkenRabbit

ответ

0

Ваш браузер сохраняя куки сессии вокруг? Это звучит для меня так, как если бы ваш браузер не держал ваш cookie сеанса после входа в систему, поэтому последующие запросы к /loggedin не выполняются.

+0

Почему браузер не сохранит файл cookie? Предположим, что это поведение по умолчанию! –

+0

Это может произойти по многим причинам: например, когда cookie установлен, он устанавливается с истечением срока. – rdegges

2

Я думаю, что у rdegges есть часть идеи, поскольку файлы cookie и переменные сеанса являются частью того, что делает управление состоянием. Я думаю, что bodyParser также требуется, но я опустил его здесь.

Я использую паспорт на своем веб-сайте (аутентификация в таблице пользователей MongoDB), и здесь выдержки из моего кода.

/server.js:

var cookieParser = require('cookie-parser'); 
... 
var passport = require('passport'); 
var expressSession = require('express-session'); 
var initPassport = require('./passport/init'); 
initPassport(passport); 
... 
self.app.use(cookieParser()); 
self.app.use(expressSession({secret: 'MYSECRETISVERYSECRET', saveUninitialized: true, resave: true})); 
self.app.use(passport.initialize()); 
self.app.use(passport.session()); 
... 
var routes = require('./routes/index')(passport); 
self.app.use('/', routes); 

/passport/init.js:

var login = require('./login'); 
var signup = require('./register'); 
var User = require('../models/user'); 

module.exports = function(passport) { 
    // Passport needs to be able to serialize and deserialize users to support persistent login sessions 
    passport.serializeUser(function(user, done) { 
    console.log('serializing user: '); 
    console.log(user); 
    done(null, user._id); 
    }); 

    passport.deserializeUser(function(id, done) { 
    User.findById(id, function(err, user) { 
     console.log('deserializing user:', user); 
     done(err, user); 
    }); 
    }); 

    // Setting up Passport Strategies for Login and SignUp/Registration 
    login(passport); 
    signup(passport); 
} 

/routes/index.js:

var passport = require('passport'); 
var User = require('../models/user'); 
... 
var isAuthenticated = function (req, res, next) { 
    // if user is authenticated in the session, call the next() to call the next request handler 
    // Passport adds this method to request object. A middleware is allowed to add properties to 
    // request and response objects 
    if (req.isAuthenticated()) 
    return next(); 
    // if the user is not authenticated then redirect him to the login page 
    res.redirect('/login'); 
} 

Для чего это стоит я m не видя вашу функцию isValidated() в любом месте.

1

Может быть так много всего.

1.) Заказ как в PassportJS Facebook login isAuthenticated returns false even though authentication succeeds (порядок кажется правильным, хотя в вашем случае).

2.) Нет req.login(), как в Passport and Passport Local req.isAuthenticated always returns false

В этом случае я выбираю последний, но по другой причине, чем в этом вопросе. Вы предоставили информацию о себе LocalStrategy. Чтобы заставить пользователя войти в систему, вам нужно позвонить по телефону req.login(). Так же, как если бы вы определили свой собственный обратный вызов, как описано в документации passport: http://passportjs.org/guide/authenticate/.

8

Вы должны разрешить куки быть установлены в Междоменное

В экспресс

res.header('Access-Control-Allow-Credentials', true); 

И в настройках АЯКС

xhrFields: { 
    withCredentials: true 
} 

Вы можете найти соответствующие ответы here и here

0

У меня была такая же проблема от f orgetting добавить

request.login() 

на

app.post('/login', 
    function(request, response, next) { 
     console.log(request.session) 
     passport.authenticate('login', 
     function(err, user, info) { 
      if(!user){ response.send(info.message);} 
      else{ 

       request.login(user, function(error) { 
        if (error) return next(error); 
        console.log("Request Login supossedly successful."); 
        return response.send('Login successful'); 
       }); 
       //response.send('Login successful'); 
      } 

     })(request, response, next); 
    } 
); 

также убедитесь, что вы следующий order для инициализации

var session = require('express-session'); 

// required for passport session 
app.use(session({ 
    secret: 'secrettexthere', 
    saveUninitialized: true, 
    resave: true, 
    // using store session on MongoDB using express-session + connect 
    store: new MongoStore({ 
    url: config.urlMongo, 
    collection: 'sessions' 
    }) 
})); 

// Init passport authentication 
app.use(passport.initialize()); 
// persistent login sessions 
app.use(passport.session()); 
0

В моем случае я попробовал решение предложил JMeas вручную вызвать сохранение сеанса, но это не сработало

https://github.com/jaredhanson/passport/issues/482

req.session.save(function() { successRedirect(); }) 

После нескольких экспериментов, я только что переехал app.use (сессия ({...})) в верхней части всех вызовов промежуточного ПО и теперь req.isAuthenticated() работает, как ожидалось. Я полагаю, настройка сеанса должна быть первой промежуточной средой или, по крайней мере, до установки файлов cookie.

Разбитое вызов:

var app = express(); 

app.use(query.json()); 
app.use(query.urlencoded({ extended: false })); 
app.use(cookies()); 
app.use(express.static(path.join(__dirname, 'public'))); 
app.use(passport.initialize()); 
app.use(passport.session()); 

app.use(session({ 
    secret: 'card', 
    resave: true, 
    saveUninitialized: true 
})); 

app.use('/', routes); // this is where I call passport.authenticate() 

Фиксированный вызов:

app.use(session({ 
    secret: 'card', 
    resave: true, 
    saveUninitialized: true 
})); 

app.use(query.json()); 
app.use(query.urlencoded({ extended: false })); 
app.use(cookies()); 
app.use(express.static(path.join(__dirname, 'public'))); 
app.use(passport.initialize()); 
app.use(passport.session()); 

app.use('/', routes); 
Смежные вопросы