护照身份验证 req.isAuthenticated 始终为 false

Posted

技术标签:

【中文标题】护照身份验证 req.isAuthenticated 始终为 false【英文标题】:Passport Authentication req.isAuthenticated is always false 【发布时间】:2017-11-01 16:33:21 【问题描述】:

我的身份验证系统未按预期工作。

首先我想向你展示我的 node.js 文件

//Initialize Express Web Server
var express = require('express');
var app = express();
var http = require("http").Server(app);
var lusca = require('lusca');
var io = require("socket.io")(http);

//require needs
var api = express.Router();
var ejs  = require('ejs');
var expressValidator = require("express-validator");
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var LocalStrategy = require('passport-local').Strategy;
var session = require('express-session');
var passport = require('passport');
var morgan = require('morgan');
var mongo = require('mongodb');
var MongoStore = require('connect-mongo')(session);

//Connect to MongoDB
var mongoose = require('mongoose');
var configDB = require('./config/database.js');
mongoose.connect(configDB.url);

//Resolving paths with nodejs
var path = require('path');
app.use(express.static(path.join(__dirname+"/MP/")));

//cookie parser middleware
app.use(cookieParser());

//Body Parser Middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded(extended:false));

//Init Sessions
app.use(session(
    secret:'SOME_HIDDEN_TEXT',
    cookie:httpOnly:true/*, secure: true*/,
    saveUninitialized: false,
    resave: false,
    store: new MongoStore(mongooseConnection: mongoose.connection, autoReconnect: true)
));

//Init Passport
app.use(passport.initialize());
app.use(passport.session());

app.use(expressValidator(
  errorFormatter: function(param, msg, value) 
      var namespace = param.split('.')
      , root    = namespace.shift()
      , formParam = root;

    while(namespace.length) 
      formParam += '[' + namespace.shift() + ']';
    
    return 
      param : formParam,
      msg   : msg,
      value : value
    ;
  
));

//Security
app.use(morgan('dev'));

//app.use(lusca.csrf());
/*app.use(lusca.csp(
    "policy":
        "default-src":"'self'",
        "script-src":"'self' 'https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/*'",
        "img-src":"'self' 'http://placehold.it/*'",
        "connect-src":"'self'",
        "font-src":"*",
        "style-src":"'self' 'unsafe-inline' *"
    
));*/
app.use(lusca.hsts(maxAge:31536000));
app.use(lusca.xframe('SAMEORIGIN'));
app.use(lusca.p3p('ABCDEF'));
app.use(lusca.xssProtection(true));
app.use(lusca.nosniff());

//Init API
var User = require(path.join(__dirname+"/model/user"));
require("./MP/routes/api")(api);
app.use("/api", api);

/*app.use(function(req, res, next) 
    res.header('Access-Control-Allow-Credentials', true);
    res.header('Access-Control-Allow-Origin', "http://localhost:3000");
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
    res.header('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
    if ('OPTIONS' == req.method) 
         res.send(200);
      else 
         next();
     
);*/

//Setting up listening port
var port = 3000;

io.on("connection", function(socket)
    console.log("user connected");
);

app.set('view engine', 'ejs');
app.set("views", path.resolve(__dirname,"MP","view"));

//Render View for Angular

app.get('/', function(req,res)
    res.render("index.ejs");
    console.log(req.headers.origin);
);

http.listen(port,function()
    console.log('SERVER LISTENING ON PORT: '+port);
);

接下来是我的 Angular 应用

"use strict";

var app = angular.module("app", ["ngRoute","ui.router", "ngSanitize","ngResource"]);

app.config(["$stateProvider" , "$urlRouterProvider", "$locationProvider" , function ($stateProvider , $urlRouterProvider, $locationProvider, loginService) 
    $stateProvider
        .state("login", 
            url: "/",
            templateUrl: "partials/index.html",
            controller: "indexCtrl"
        )
        .state("register", 
            url:"/register",
            templateUrl: "partials/register.html",
            controller: "indexCtrl"
        )
        .state("home", 
            url: "/en/",
            abstract: true,
            templateUrl: "partials/home.html",
            resolve: 
                loggedIn: checkLogin
            
        )
        .state("home.news", 
            url: "",
            templateUrl: "partials/news.html",
            resolve: 
                loggedIn: checkLogin
            
        )
        .state("home.gamer", 
            url: "gamer/",
            templateUrl: "partials/gamer.html",
            resolve: 
                loggedIn: checkLogin
            
        )
        .state("home.search", 
            url: "search/",
            templateUrl: "partials/search.html",
            resolve: 
                loggedIn: checkLogin
            
        )
        .state("home.games",
            url: "games/",
            templateUrl: "partials/games.html",
            resolve: 
                loggedIn: checkLogin
            
        )
        .state("home.verify", 
            url: "verify/",
            templateUrl: "partials/verify.html",
            resolve: 
                loggedIn: checkLogin
            
        );
        $urlRouterProvider.otherwise("/");
        $locationProvider.html5Mode(
            enabled: true,
            requireBase: false
        );
]);

function checkLogin(loginService)
    return loginService.loggedIn();

这是我的登录服务

"use strict";

app.factory("loginService",["Api", "$location", "$state", "$q", "$rootScope",  function (Api,$location,$state,$q,$rootScope) 
    return 
        login: function (user,scope) 
            Api.login.post(user, function(regRes)
                console.log(regRes.data);
                if(regRes.data.error)
                    scope.error =  error : regRes.data.error;
                else if(regRes.data.success === 1)
                    $state.go("home.news");
                
            );
        ,
        loggedIn: function()
            var deferred = $q.defer();

            Api.login.get(function(user)
                if(user.data != "0")
                    $rootScope.currentUser = user;
                    deferred.resolve();
                else
                    $rootScope.currentUser = null;
                    deferred.reject();
                    $state.go("login");
                  
            );

            return deferred.promise;
        
    
]);

最后但并非最不重要的是我的 api

'use strict';
var User = require("../../model/user");
var passport = require("passport");
var LocalStrategy = require("passport-local").Strategy;

passport.use(new LocalStrategy(usernameField: "e", passwordField: "p",function(email, password, done)
    var user = new User();
    user.findEmail(escape(email),function(err, user)
        if(err)
            throw err;
        
        if(!user)
            return done(null,false, error: "Email or Password is wrong. Please try again.");
        
        user.comparePw(escape(password),user.password,function(err, isMatched)
            if(!isMatched)
                return done(null,false, error: "Email or Password is wrong. Please try again.");
            else
                return done(null,user);
            
        );
    );
));

passport.serializeUser(function(user,done)
    done(null, user.id);
);

passport.deserializeUser(function(user,done)
    var user = new User();
    user.findUserById(user, function(err, user)
        done(err,user);
    );
);

module.exports = function(router)
    router.get("/user", function(req, res)
        var user = new User();
        user.getGamer(function(err,response)
            if(err)
                throw err;
            else
                res.json(response);
            
        );
    );
    router.post("/user/login", function(req, res, next) 
        passport.authenticate('local', session: true,function(err, user, info) 
            console.log(user + " " + info + " " + err);
            if (err)  return next(err); 
            if (!user)  return res.json(error: "Email or Password is wrong. Please try again."); 
            if(user.confirm == 0) return res.json(error: "Please confirm your email address and try again.")
            console.log(req.user);
            req.logIn(user, function(err) 
                console.log(req.session.id);
                console.log(req.user); //req.user is defined
                console.log(req.isAuthenticated()); //req.isAuthenticated() is true
                if (err)  return next(err); 
                res.json(success: 1);
            );
        )(req, res, next);
    );
    router.get("/user/login", function(req, res, next) 
        console.log(req.isAuthenticated()); //returns false
        res.send(req.isAuthenticated() ? req.user: "0"); //send object with data:"0";
    );
;

更新:这是我的 API 服务

app.factory("Api", ["$resource", function($resource)
    return 
        gamer: $resource("/api/user/:id", _id: "@id",
            "get":  
                method: "GET",
                interceptor: 
                    response: function(response) 
                        return response;
                    
                
            ,
            "post":
                method: "POST",
                interceptor:
                    response: function(response)
                        return response;
                    
                
            
        ),
        login: $resource("/api/user/login", ,
            "post":
                method: "POST",
                interceptor:
                    response: function(response)
                        return response;
                    
                
            ,
            "get":
                method: "GET",
                interceptor:
                    response: function(response)
                        return response;
                    
                
            
        )  
    
]);

在我调用loggedIn 函数时,我得到了一个带有数据的对象的响应:“0”。我不知道为什么 req.isAuthenticated() 在通过护照成功登录时总是错误的。一个名为 connect.sid 的会话 cookie 已正确设置,并获得与存储在 mongoose 数据库中的会话 cookie 相同的值。如果我在登录后立即通过 console.log isAuthenticated,我会得到 true 的响应,否则它总是 false。我也尝试允许 CORS,但它没有奏效。我在谷歌上搜索了一整天以找到解决方案。有人可以帮助我吗?

问候中国

【问题讨论】:

当你调用你的 API 时,你把withCredentials: true 放了吗?否则,您的 AJAX 请求将无法获取 (httpOnly) cookie。 我更新了我的帖子。我认为我没有这样做:/ 【参考方案1】:

尝试将withCredentials 参数放入您的请求中。

...    
login: $resource("/api/user/login", ,
                "post":
                    method: "POST",
                    withCredentials: true,
                    interceptor:
                        response: function(response)
                            return response;
                        
                    
                ,
                "get":
                    method: "GET",
                    withCredentials: true,
                    interceptor:
                        response: function(response)
                            return response;
                        
                    
                
            )   
...

见:here

让我知道它是否有效!

【讨论】:

仍然返回 false :/【参考方案2】:

好吧,我自己发现了。我最大的错误是我忘记为 cookie 解析器设置相同的密钥,如下所示。

app.use(cookieParser("SAME_SECRET")); //i let this blank

app.use(session(
    secret:'SAME_SECRET',
    cookie:httpOnly:true/*, secure: true*/,
    saveUninitialized: true,
    resave: true,
    store: new MongoStore(mongooseConnection: mongoose.connection, autoReconnect: true)
));

【讨论】:

以上是关于护照身份验证 req.isAuthenticated 始终为 false的主要内容,如果未能解决你的问题,请参考以下文章

未知的身份验证策略护照

nodejs护照身份验证令牌

使用身份验证护照系统覆盖 laravel 中 apis url 的身份验证重定向

Facebook iOS SDK 和护照-facebook 身份验证

节点护照错误:未知身份验证策略“本地登录”

使用电子邮件进行身份验证时,NestJS 护照身份验证返回 401