检查用户是否登录或用户注销时未调用 Passport JS deserializeUser

问题描述 投票:0回答:1

Client 是一个 React 应用程序。服务器使用express、express-session Passport、cors和body-parser。

当我检查用户是否从客户端网页登录或用户从客户端网页注销时,不会调用 Passport JS deserializeUser。但是当我用 Postman 测试检查用户是否登录(GET localhost:5000/api/auth/is_logged_in)或注销(GET localhost:5000/api/auth/logout)时,它会被调用

我可以通过使用 console.log() 并在代码中放置断点来确认 deserializeUser 正在被调用。一切都与 Postman 配合良好。

我创建了一个中间件函数 isLoggedIn

为什么我的 isLoggedIn 中间件可以在 Postman 中工作,但不能在我的 React 应用程序客户端中工作?

服务器-index.js

const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');

const session = require('express-session');
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const bcrypt = require('bcrypt');

require("dotenv").config();
const port = process.env.PORT;
const baseUrl = process.env.BASEURL; 

const app = express()

app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

app.set('trust proxy', 1);

// passport and session startup - start vvvv
const userQuery = require('./db/userQueries');

// configure passport LocalStrategy
passport.use(
    new LocalStrategy(
        {
            usernameField: 'email',
            passwordField: 'password'
        },
        async (username, password, done) => {
            const errMsg = 'Incorrect username or password';
            try {
                const user = await userQuery.findUserByEmail(username);
                // if did not find user
                if (!user) return done(null, false, { message: errMsg });
                // found user, try to match hashed password        
                const matchedPassword = await bcrypt.compare(password, user.password_hash);
                // if password hashes do not match
                if (!matchedPassword) return done(null, false, { message: errMsg });
                // password hashes match                   
                return done(null, user);
            } catch (err) {
                return done(err);
            }
        }
    )
);

// passport serializeUser/deserializeUser
passport.serializeUser((user, done) => {
    done(null, user.guid);
});
passport.deserializeUser( async (guid, done) => {  
    const user = await userQuery.findUserByGuid(guid); 
    return done(null, user);
});

// session configuration
// app.use(session) BEFORE app.use(passport....)

// NOTE: for local testing, set cookie: secure to false. 
// setting cookie: {secure: true} , the cookie will only be set over an 
// https connection, and not over an http connection
// https://stackoverflow.com/questions/71184167/why-setting-the-cookie-secure-to-true-in-express-session-allows-session-id-and-d
app.use(session({
    secret: process.env.SESSION_SECRET || 'not_so_secret',
    resave: true,
    cookie: {
        maxAge: 1000 * 60 * 60 * 24,
        secure: false,
        httpOnly: true,
        path: '/'
    },
    saveUninitialized: true  
}));

// passport configuration
app.use(passport.initialize());
app.use(passport.session());

// passport and session startup - end ^^^^

// routes
const authRouter = require('./routes/auth');
app.use('/api/auth', authRouter);

app.listen(port, () => {
    console.log(`Server started on port ${port}.`)
});

module.exports = app;

服务器 - auth.js

const express = require('express');
const authRouter = express.Router();
const passport = require("passport");

authRouter.post('/register', async (req, res) => {

});

authRouter.post('/login', (req, res, next) => {
    passport.authenticate('local', (err, theUser, failureDetails) => {
        if (err) {
            res.status(500).json({ message: "Something went wrong authenticating user" });
            return;
        }
        if (!theUser) {
            res.status(401).json(failureDetails);
            return;
        }
        // save user in session
        req.login(theUser, (err) => {
            if (err) {
              res.status(500).json({ message: "Session save went bad." });
              return;
            }
            res.status(200).json({ errors: false, user: theUser });
        });
    })(req, res, next);
});

authRouter.get('/logout', (req, res, next) => {
    req.logout(err => {
        if (err) {
            return next(err);
        }
        res.redirect(`/login`);
    })
})

function loggedIn(req, res, next) {
    if (req.isAuthenticated()) {
        next();
    } else {        
        res.status(401).send('not logged in');
    }
};

authRouter.get('/is_logged_in', loggedIn, (req, res) => {
    res.status(200).send("User logged in")
});

authRouter.get('/login', (req, res) => {
    res.send('Login Page');
});

module.exports = authRouter;

服务器-app.js

import React, { Fragment } from 'react';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import Header from './components/Header';

import LogIn from './components/LogIn';
import Register from './components/Register';
import LogOut from './components/LogOut';
import Home from './components/Home';

import './App.css';

function App() {

    const isLoggedIn = async () => {
        const response = await fetch(`${baseApi}/auth//is_logged_in`);
        if (response.status === 200) {
            return true
        } else {
            return false
        }
    }

    const checkedLoggedIn = async () => {
        let loggedInStatus = ""
        if (await isLoggedIn()) {
            loggedInStatus = "Yes, Logged in"
        } else {
            loggedInStatus = "NOT Logged in"
        }
        document.getElementById("testData").value = loggedInStatus
    }  

    return (
        <Router>
            <Fragment>
                <Header ref={headerRef} />

                <button onClick={checkedLoggedIn}>Test</button>
                <input type="text" id="testData" name="testData" ></input>

            </Fragment>
            <Routes>
                <Route
                    path="/login"
                    element={<LogIn />}
                />
                <Route
                    path="/register"
                    element={<Register />}
                />
                <Route
                    path="/logout"
                    element={<LogOut />}
                />
                <Route exact path="/" element={<Home />} />
              </Routes>
        </Router>
    );
}

export default App;

服务器-logon.js

try { 
  const loginBody = {
      email: sanitized.email,
      password: formData.password
  }
  const response = await fetch(`${baseApi}/auth/login`, {        
      method: "POST",
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'            
      },           
      body: JSON.stringify(loginBody)
  });

  // successfull login
  if (response.status === 200) {
    
  } else if (response.status === 401) {
    
  } else if (response.status === 500) {
    
  } else {
    
    console.error('Login request failed with status:', response.status);
  }       

} catch (err) {
  console.error(err.message);
}

当我通过 Postman 测试时,在 isLoggedIn 中,req.session.passport 有一个带有用户 ID 的对象。 req.session.user 有一个用户对象,req.IsAuthenticated() 返回 true。

当我通过 React 应用程序进行测试时,在 isLoggedIn 中,req.session.passport 和 req.session.user 属性不可用。另外,req.IsAuthenticated() 返回 false。

postman deserialization passport.js logout
1个回答
0
投票

在这里找到答案:https://github.com/jaredhanson/passport/issues/446

在我的index.js中需要:

app.use(cors({
 origin: 'http://localhost:3000`,
 credentials: true,
 allowedHeaders: ['Content-Type'], // this is needed for sending JSON
}));

在我的获取中我需要:

fetch('http://localhost:5000/private', { credentials: 'include'} );
© www.soinside.com 2019 - 2024. All rights reserved.