首页 > 解决方案 > Passport JS - 帮助,没有调用反序列化用户

问题描述

我有一个调用 Express API 的 React 应用程序,它使用 Passport JS 通过本地策略进行身份验证。

客户端登录页面调用/auth/login路由成功。req.user被发送回客户端,并调用序列化函数(我有一个打印的 console.log)。

Router.post('/login', passport.authenticate('local'), (req, res) => {
    res.send(req.user);
})

后续请求从中获取用户信息/auth/instructor不起作用。req.user返回 undefined 并且deserializeUser()永远不会被调用。

Router.get('/instructor', (req,res)=>{
    console.log(req.user)
    if(req.user) res.send(req.user)
    else res.send({username: "No user logged in"})
})

我相信我的护照和会话配置设置正确。

const passportLocal = require('passport-local').Strategy
const bcrypt = require('bcryptjs')
const instructor = require('../Models/instructor.model')

module.exports = function(passport){
    
    const strategy = new passportLocal( (username, password, done)=> {
        console.log(username, password)
        instructor
            .findOne({username})
            .then( instructor => {
                if (!instructor) return done(null, false)
                if (bcrypt.compareSync(password, instructor.password)) return done( null, instructor)
                return (null, false)
            })
            .catch( error => console.log(error))
    })

    passport.use(strategy)

    passport.serializeUser( (user, done)=> {
        console.log('serialize', user._id)
        done(null, user._id)
    })

    
    passport.deserializeUser( (id, done)=> {
        console.log('de-serialize', id)
        instructor.findById(id).then( instuctor => done( null, instructor))
    })
}

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
const cors = require('cors')
const session = require('express-session')
const passport = require('passport')

// Import routers
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
const pupilsRouter = require('./routes/pupils.routes');
const authRouter = require('./routes/auth.routes');


// Connect to database
require('./config/mongoose.config.js');


var app = express();


// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

app.use(logger('dev'));
app.use(express.static(path.join(__dirname, 'public')));
app.use(cookieParser("secret"));
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(session({
    secret: "secret",
    resave: true, 
    saveUninitialized: true, 
    cookie: {secure: false}
}))


app.use(cors({
    origin: "http://localhost:3003",
    credentials: true,
}))





// Initialize Passport Middleware
app.use(passport.initialize())
app.use(passport.session())
require('./config/passport.config')(passport)


// Use Routers
app.use('/api', indexRouter);
app.use('/api/users', usersRouter);
app.use('/api/pupils', pupilsRouter);
app.use('/api/auth', authRouter);
app.get('/api/ping', (req, res) => res.send("server is working"))

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  next(createError(404));
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

const Router = require('express').Router()
const Instructor = require('../Models/instructor.model');
const bcrypt = require('bcryptjs');
const passport = require('passport');

Router.post('/register', (req, res) => {
    Instructor.findOne({username: req.body.username}).then( results => {
        if (!results) {
            const instructorData = {...(req.body), password: bcrypt.hashSync(req.body.password) }
            Instructor.create(instructorData).then(console.log)
            res.send("Instructor registered")
        } else {
            res.status(400).send("Instructor Already Exists")
        }
    } )

    
})

Router.post('/login', passport.authenticate('local'), (req, res) => {
    res.send(req.user);
})

Router.get('/instructor', (req,res)=>{
    console.log(req.user)
    if(req.user) res.send(req.user)
    else res.send({username: "No user logged in"})
})
 
module.exports = Router

这是我要开始工作的客户端代码。单击配置文件按钮应该从会话中获取用户并显示用户名。

import React, { useState, useEffect } from 'react'
import { NavLink} from 'react-router-dom'
import styled from 'styled-components';
import axios from 'axios'


import Logo from './Logo'
axios.defaults.withCredentials = true;
function Header() {

    const [user, setUser] = useState({})
    useEffect( ()=>{
        axios
            .get( 'http://localhost:3000/api/auth/instructor')
            .then( response => setUser( response.data ))
           
    } ,[])

    const getUser = ()=> {
        axios
        .get( 'http://localhost:3000/api/auth/instructor')
        .then( response => setUser( response.data ))
    }


    return (
        <StyledDiv>
            <Logo/>
            <div className="auth">
                <NavLink to="/auth/login"> Login </NavLink>
                <NavLink to="/auth/register"> Register </NavLink>
                <button className="profile-button" onClick={getUser}>{user.username || "Get User"}</button>
            </div>

        </StyledDiv>
    )
}


 const StyledDiv = styled.div`
    width: 100vw; height: 90px; 
    display: grid; place-content: center;
    position: relative;
    box-shadow: 0px 3px 5px 5px lightgray, 0px 2px 1px 1px black;
    
    div.auth {
        position: absolute;
        right: 50px; top: 35px;

        a {
            margin-right: 7px;
        }
    }

    .user-profile {
        background: purple;
        color: white;
    }
 
 `

export default Header

检查网络请求,客户端似乎正在设置 SID cookie 并毫无问题地发出 cors 请求。但是 req.user 没有数据..

网络请求截图

感谢这里的任何帮助,我要疯了。

标签: javascriptreactjsaxiospassport.jspassport-local

解决方案


您的回调函数中似乎有一个错字 ( instuctor)。

使固定:

passport.deserializeUser( (id, done)=> {
        console.log('de-serialize', id);
        instructor.findById(id).then((instructor) => done( null, instructor));
    })

如果您使用的是 VS Code,我还推荐一个拼写检查插件


推荐阅读