我已经按照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,要么我在最初登录时没有检索到用户,你知道我做错了什么吗?
多谢了
1条答案
按热度按时间bxfogqkk1#
一旦您通过授权登录,您就不必对用户数据做任何事情,passport中间件就可以完成这项工作,但是我们至少应该为他们交换凭据设置正确的条件,尝试稍微更改设置,看看效果如何:
本部分:
并在前端Axios调用中稍微更新此部分:
我不知道你是否已经在本地主机或部署后的问题,如果它仍然不工作,比我们可能要解决的cookie会话。