mongodb ExpressJS中的Passport.js身份验证未在React中返回res.user

yjghlzjz  于 2023-01-08  发布在  Go
关注(0)|答案(1)|浏览(112)

我已经按照Medium上的指南使用MERN堆栈实现了Passport js,虽然我的身份验证工作正常,但我很难在路由之间持久化用户。以下是我的代码片段:

后端

Server.js安装程序(其中一部分):

const mongoose = require('mongoose')
const MongoStore = require('connect-mongo')
const passport = require('./passport/setup')

const MONGO_URI = 'db'

const app = express();

mongoose
  .connect(MONGO_URI, { useNewUrlParser: true })
  .then(console.log(`MongoDB connected ${MONGO_URI}`))
  .catch(err => console.log(err))

app.set("")

const PORT = process.env.PORT || 5000;

if (PORT !== 5000) {
  app.use(enforce.HTTPS({ trustProtoHeader: true }));
}

app.use(cors({
  origin: true,
  credentials: true,
}))
app.options('*', cors())
app.use(
  session({
    secret: "secret",
    resave: false,
    saveUninitialized: true,
    store: MongoStore.create({ mongoUrl: MONGO_URI })
  })
);
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

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

Passport.js本地策略设置:

const bcrypt = require('bcryptjs');
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const User = require('../models/User')

passport.serializeUser((user, done) => {
    done(null, user.id);
})

passport.deserializeUser((id, done) => {
    User.findById(id, (err, user) => {
        done(err, user);
    });
});

passport.use(new LocalStrategy({ usernameField: "email" }, (email, password, done) => {
    User.findOne({ email: email })
        .then(user => {
            if (!user) {
                return done(null, false, { message: 'No User Found' })
            } else {
                bcrypt.compare(password, user.password, (err, isMatch) => {
                    if (err) throw err;

                    if (isMatch) {
                        return done(null, user);
                    } else {
                        return done(null, false, { message: "Wrong Password" });
                    }
                });
            }
        })
        .catch(err => {
            return done(null, false, { message: err });
        });
})
);

module.exports = passport;

登录路径:

router.post("/new-login", async (req, res, next) => {
    passport.authenticate("local", function (err, user, info) {
        if (err) {
            return res.status(400).json({ errors: err });
        }
        if (!user) {
            return res.status(400).json({ errors: "No user found" });
        }
        req.logIn(user, function (err) {
            if (err) {
                return res.status(400).json({ errors: err });
            }
            return res.status(200).json({ success: `logged in ${user.id}` });
        });
    })(req, res, next);
})

前端React:

过账登录数据:

export const postData = async (url, data) => {
    try {
        console.log('posting this ', data)
        const config = {
            withCredentials: true,
            headers: {
                'Content-Type': 'application/json',
                'Access-Control-Allow-Origin': 'backend',
                'Access-Control-Allow-Methods': 'GET,PUT,POST,DELETE'
            }
        }
        const response = await axios.post(url, data, config);
        console.log('getting this', response)
        return {
            data: response.data,
            error: "",
            success: true,
        };
    } catch (exp) {
        console.log('Error', exp)
        return {
            success: false,
            error: exp.response.data,
        };
    }
};

Axios电话:

let response = await postData('/login/new-login', { email, password })

当尝试登录时,所有这些操作都有效,并从登录路径返回登录成功消息user.id,但当我查看Axios响应时,没有引用任何用户或会话,如下所示:

我可能不明白用户是如何从后端传递到React的,但是在Passport中的req.LogIn之后,res.user不应该存在吗?或者我应该将user.id保存为全局React状态,并在每次向受保护的路由发出请求时附加它吗?现在,如果我向受保护的路由发出GET请求,我会收到req.user undefined消息。
前端Axios呼叫:

export const getData = async (url) => {
    console.log('not called?')
    try {
        const config = {
            withCredentials: true,
            headers: {
                'Content-Type': 'application/json',
                'Access-Control-Allow-Origin': 'backend',
                'Access-Control-Allow-Methods': 'GET,PUT,POST,DELETE'
            }
        }
        const response = await axios.get(url, config);
        console.log('response? ', response)
        return {
            data: response.data,
            error: "",
            success: true,
        };
    } catch (exp) {
        return {
            success: false,
            error: exp.response.data,
        }
    }
}

后端保护路由:

router.get("/new-protected", passport.authorize('local', { failureRedirect: '/login' }), (req, res) => {
    console.log('whats request?', req.user)
    res.send(`Hello, logged in`);
})

当我尝试这样做的时候,我删除了中间件,看看req是什么样子的,但是我总是得到未定义的req.user,所以我猜要么我应该在我的axios调用中以某种方式传递req.user,要么我在最初登录时没有检索到用户,你知道我做错了什么吗?
多谢了

bxfogqkk

bxfogqkk1#

一旦您通过授权登录,您就不必对用户数据做任何事情,passport中间件就可以完成这项工作,但是我们至少应该为他们交换凭据设置正确的条件,尝试稍微更改设置,看看效果如何:
本部分:

app.use(cors({
  origin: //put the EXACT URL you host from Vercel 
  method: 'GET,PUT,POST,DELETE'
  credentials: true,
}))
app.set('trust proxy', 1)
app.use(
   session({
     secret: "secret",
     resave: false,
     saveUninitialized: true,
     store: MongoStore.create({ mongoUrl: MONGO_URI })
  })
);
app.use(express.json()); // optional: you can uninstall bodyParser since express have now his own module so you can just replace with this line. 

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

并在前端Axios调用中稍微更新此部分:

const config = {
    withCredentials: true,
};

我不知道你是否已经在本地主机或部署后的问题,如果它仍然不工作,比我们可能要解决的cookie会话。

相关问题