簡體   English   中英

快遞和護照:req.isAuthenticated()登錄后返回false

[英]express session and passport: req.isAuthenticated() return false after login

我需要在后端使用快遞護照處理Angular應用程序上的持久會話。 成功登錄后,如果我對返回request.isAuthenticated()的快速API進行http調用(使用angular $ http ),它將始終返回false。 當我登錄並使用Postman對API進行http調用時,情況並非如此,在這種情況下,我得到了真的。

這是我在服務器上的配置:

server.js

const
        express = require('express'),
        config = require("../config"),
        path = require('path'),
        bodyParser = require('body-parser'),
        cookiePraser = require('cookie-parser'),
        cors = require('cors'),
        winston = require("winston"),
        morgan = require("morgan"),
        mongoose = require("mongoose"),
        passport = require("passport"),
        session = require("express-session"),
        flash = require("connect-flash"),



let app = express(),
    server = require("http").Server(app),
    io = require("socket.io")(server);

const sessionKey = "mySessionKey";




/*
 * ---------------------------------------------------------------------------------------
 * app configuration
 * ---------------------------------------------------------------------------------------
 */

// Add headers
app.use(function (req, res, next) {

    // Website you wish to allow to connect
    res.setHeader('Access-Control-Allow-Origin', req.headers.origin);

    // Request methods you wish to allow
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');

    // Request headers you wish to allow
    res.setHeader('Access-Control-Allow-Headers', "Content-Type,X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5,  Date, X-Api-Version, X-File-Name");

    // Set to true if you need the website to include cookies in the requests sent
    // to the API (e.g. in case you use sessions)
    res.setHeader('Access-Control-Allow-Credentials', true);

    // Pass to next layer of middleware
    next();
});



app.use(morgan("dev")); 
app.use(bodyParser.json({limit: "50mb"}));
app.use(cookiePraser(sessionKey));    
app.use(express.static("public"));



app.use(session({
    secret: sessionKey,
    resave: true,
    saveUninitialized: true,
    cookie: {
        secure: false,
        httpOnly: false
    }
}));
app.use(passport.initialize());
app.use(passport.session()); 

require("./passportConfig")(passport); // passport configuration


app.get("api/test", function(req, res){
    return json({isAuthenticated: req.isAuthenticated()});
})

// [..]

passportConfig.js

const   LocalStrategy   =   require("passport-local").Strategy,
        User            =   require("./models/User");



module.exports = function(passport) {


    // used to serialize the user for the session
    passport.serializeUser(function(user, done) {
        done(null, user.id);
    });

    // used to deserialize the user
    passport.deserializeUser(function(id, done) {
        User.findById(id, function(err, user) {
            done(err, user);
        });
    });





    passport.use('local-signup', new LocalStrategy({

            usernameField : 'email',
            passwordField : 'password',
            passReqToCallback : true // allows us to pass back the entire request to the callback
        },

        function(req, email, password, done) {

            // asynchronous
            // User.findOne wont fire unless data is sent back
            process.nextTick(function () {

                User.findOne({'local.email': email}, function (err, user) {
                    if (err)
                        return done(err);

                    // check to see if theres already a user with that email
                    if (user) {
                        return done(null, false, req.flash('signupMessage', 'That email is already taken.'));
                    } else {

                        // if there is no user with that email
                        // create the user
                        let newUser = new User();

                        // set the user's local credentials
                        newUser.local.email = email;
                        newUser.local.password = newUser.generateHash(password);

                        // save the user
                        newUser.save(function (err) {
                            if (err)
                                throw err;
                            return done(null, newUser);
                        });
                    }

                });

            });

        }
    ));







    passport.use('local-login', new LocalStrategy({
            usernameField : 'email',
            passwordField : 'password',
            passReqToCallback : true // allows us to pass back the entire request to the callback
        },
        function(req, email, password, done) { // callback with email and password from our form

            // find a user whose email is the same as the forms email
            // we are checking to see if the user trying to login already exists
            User.findOne({ 'local.email' :  email }, function(err, user) {
                // if there are any errors, return the error before anything else
                if (err)
                    return done(err);

                // if no user is found, return the message
                if (!user)
                    return done(null, false, req.flash('loginMessage', 'No user found.')); // req.flash is the way to set flashdata using connect-flash

                // if the user is found but the password is wrong
                if (!user.validPassword(password))
                    return done(null, false, req.flash('loginMessage', 'Oops! Wrong password.')); // create the loginMessage and save it to session as flashdata

                // all is well, return successful user
                return done(null, user);
            });

        }
    ));





};

loginService.js(公開登錄功能):

this.login = function(email, password) {
        return new Promise((resolve, reject) => {

            $http({
                url: serverBaseURL + "/api/login",
                method: "POST",
         `enter code here`       data: JSON.stringify({
                    email: email,
                    password: password
                }),
                headers: {
                    "Content-Type": "application/json",
                    "Accept": "application/json"
                }    
            }).then(function (response) {
                resolve(response);
            }, function (errorResponse) {
                reject(errorResponse);
            });
        });
    };

在控制器中我執行登錄,然后我再次進行http調用以檢查我是否真的登錄:

loginCtrl.js

loginService.login($scope.email, $scope.password).then(response => {
    if (response.status === 200) {

        // check if I am really logged in, include the connect.sid cookie in the call => withCredentials = true
        $http({
                url: serverBaseURL + "/api/test",
                method: "GET",
                headers: {
                    "Accept": "application/json"
                },
                withCredentials: true,

            }).then(function (response) {
                console.log(response);    // I always get false in the response
            }, function (errorResponse) {
                console.log(errorResponse);
            });
    }
}, error => {
    // handle error
});

// [..]

我注意到兩件事:

  • 在對“api / test”的第一次http調用中,即使我在$ http的屬性中設置了withCredentials = true,也不包括connect.sid cookie。
  • 如果我再次調用“api / test”,這次connect.sid cookie包含在請求中,但是我在響應中總是為false(服務器端的request.isAuthenticated()返回false)。

知道我錯過了什么嗎?

我發現了這個問題,因為我有同樣的情況,總是從request.isAuthenticated()和狀態401得到假。解決方案是@Mukesh Sharma寫的是不要忘記在客戶端前端添加:

{ withCredentials: true }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM