AngularJS passportJS用户在页面重新加载后注销

3
我按照Chirp MEAN栈教程为我的网站(https://github.com/hwz/chirp)添加了passportJS身份验证。
只要我停留在单页面应用程序中,登录和注册就可以正常工作(passport,在MongoDB中存储和查找用户)。但是,如果我在浏览器中点击刷新/重新加载,用户似乎不再处于登录状态。
有人知道如何在重新加载后恢复页面的会话/用户吗?我已经苦苦挣扎了几天,但在网络上找不到任何信息。真的非常感谢每一位提供帮助的人。
如果用户没有登录,网站菜单将要求进行登录/注册。
如果用户已登录,则菜单将显示一个用户下拉菜单。
在Angular中,我使用以下代码来创建页面菜单:
<a ui-sref="signin" class="btn btn-success" role="button" ng-hide="authenticated">Login</a>
<a ui-sref="register" class="btn btn-primary" role="button" ng-hide="authenticated">Register</a>

<span class="dropdown" ng-show="authenticated">
  <button class="btn btn-success dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
     {{current_user}}
    <span class="caret"></span>
  </button>
  <ul class="dropdown-menu" aria-labelledby="usermenu">
    <li><a ui-sref="#" ng-click="signout()">Logout</a></li>
  </ul>
</span>

页面重新加载后,ng-show="authenticated" 再次为 false。 有一个 connect.sid cookie 在页面重新加载后仍然存在,但似乎没有被考虑在内。

AngularApp.js 如下:

var app = angular.module('myApp', ['ui.router']);
...
app.run(function($rootScope, $http) 
{
  $rootScope.authenticated = false;
  $rootScope.current_user = '';

  $rootScope.signout = function()
  {
      $http.get('auth/logout');
      $rootScope.authenticated = false;
      $rootScope.current_user = '';
  };
});

我猜,我需要在这里添加代码?
AuthenticationController.js看起来像:
var app = angular.module('myApp');

app.controller('authController', function($scope, $http, $rootScope, $location)
{
  $scope.user = {username: '', password: ''};
  $scope.error_message = '';

  $scope.login = function()
  {
    $http.post('/auth/login', $scope.user).success(function(data)
    {
      if(data.state == 'success')
      {
        $rootScope.authenticated = true;
        $rootScope.current_user = data.user.username;
        $location.path('/');
      }
      else
      {
        $scope.error_message = data.message;
      }
    });
  };

  $scope.register = function(){
    $http.post('/auth/register', $scope.user).success(function(data)
    {
      if(data.state == 'success')
      {
        $rootScope.authenticated = true;
        $rootScope.current_user = data.user.username;
        $location.path('/');
      }
      else
      {
        $scope.error_message = data.message;
      }
    });
  };
});

Server.js看起来像:

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require('express-session');
var passport = require('passport');

var api = require('./routes/api');

var app = express();
//initialize mongoose schemas
require('./models/models');
var mongoose = require('mongoose');                         //add for Mongo support
mongoose.connect('mongodb://localhost/myApp');  //connect to Mongo

app.set('port', process.env.PORT || 3000);

//Middleware
app.use(logger('dev'));
app.use(session({ secret: 'changedforstackoverflow', rolling: true, resave: true, saveUninitialized: false }));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(__dirname + '/../frontend'));     //serve static assets
app.use(passport.initialize());
app.use(passport.session());

//// Initialize Passport
var initPassport = require('./passport-init');
initPassport(passport);

var authenticate = require('./routes/authenticate')(passport);

app.use('/api', api);
app.use('/auth', authenticate);
...

如果需要,我可以发布更多的代码。但是据我所见,后端的身份验证工作正常。只有在重新加载后,Angular无法从cookie中获取会话,对吗?

1个回答

3

好的,我终于成功了。

据我所知,passport会自行处理会话和cookie。由于HTMLonly属性的保护,我也无法从cookie中读取数据。

那么该怎么办呢?我在后端添加了控制台日志,以查看重新加载请求是否仍然具有有效的用户。

我直接在server.js(后端/节点)之后添加了以下内容:

app.use('/auth', authenticate):

this:

app.use(function (req, res, next) {
  console.log(req.isAuthenticated());
  console.log(req.user);
  next();
});

现在我在服务器控制台中看到,在页面重新加载后,每个请求仍然具有有效的用户,但是angular不知道这一点。

我之前发布的帖子中关于放置一些代码的地方是正确的。 App.run必须从后端获取用户数据!

因此,我添加了这个函数(前端/angular):

app.run(function($rootScope, $http, $location) 
{
  $rootScope.loggedIn = function()
  {
    $http.post('/auth/isloggedIn').success(function(data)
    {
      if(data.state == 'success')
      {
        $rootScope.authenticated = true;
        $rootScope.current_user = data.user.username;
        $location.path('/');
      }
      else
      {
        $rootScope.authenticated = false;
        $rootScope.current_user = '';
        $location.path('/');
      }
    });
  };

  $rootScope.loggedIn();

现在我们需要构建一个函数,在后端有用户登录时返回用户数据。在上面的loggedIn函数中调用的url需要执行某些操作。因此,我将以下内容添加到authenticate路由器(backend/node)中:

//is logged in
router.post('/isloggedin', function(req, res){
    if(req.isAuthenticated())
    {
        res.send({state: 'success', user: req.user});
    }
    else
    {
        res.send({state: 'failure', user: null});
    }
});

最后一步是验证它是否可以支持多个用户,所以我使用了两个浏览器,并用不同的用户登录并刷新了页面。两个用户都被正确地识别并且“自动登录”了。
太好了! ;-)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接