【发布时间】:2019-01-16 16:29:57
【问题描述】:
我设置了一个 API 来访问我的后端,并实现了快速会话来验证用户身份。
当使用 Postman 登录,然后访问受保护的 GET 请求时,它工作正常。
但我正在构建的 React SPA 在登录后似乎无法使用会话进行身份验证。
我尝试了很多我在网上找到的建议(更改 CORS 标头、在 React 中使用显式 cookie 设置、更改我存储会话的方式……)但似乎都没有解决问题。
我会尝试包含相关的代码 sn-ps:
服务器端(REST API)
会话和 CORS 中间件:
//Session Middleware
api.use(session({
genid: (req) => {
console.log('Inside session middleware');
console.log(req.sessionID)
return uuid()
},
cookie: {
maxAge: 60000
},
secret:"123",
resave:false,
saveUninitialized:true,
store: new MongoStore({
mongooseConnection:db,
clear_interval: 3600
})
}));
// CORS
api.use(function(req,res,next){
res.header("Access-Control-Allow-Origin", "http://localhost:3000");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.header("Access-Control-Allow-Credentials", "true")
next();
})
登录功能和护照验证:
exports.login = (req,res,next) => {
passport.authenticate('local',(err,user,info) =>{
//... (login handling)
})(req,res,next);
}
// Passport Middleware
passport.use(new LocalStrategy(
(username, password, done) => {
Promotor.findOne({username:username,password:password}, (err,user) =>{
if (err) {
done(err,null);
}
if (!user){
done(null,false,{message:'Invalid Credentials!'})
} else {
done(null,user)
}
});
}
));
// Passport serializing
passport.serializeUser((user,done) => {
done(null,user._id);
});
passport.deserializeUser((id,done) => {
Promotor.findById(id,function(err,user){
if(err){
done(err,false);
} else {
done(null,user);
}
})
})
受保护的 GET 函数
(isAuthenticated() 在我的 SPA 中使用 axios 时返回 false)
exports.getNameById = (req,res) => {
console.log(req.session)
console.log(req._passport)
if(!req.isAuthenticated()){ //RETURNS FALSE IN REACT & TRUE IN POSTMAN
return res.status(401).send();
}
return controller.getDocumentById(Promotor,'firstname lastname',req,res);
}
客户端(React SPA)
Axios 请求登录
(适用于 Postman 和应用程序,并正确创建会话)
handleSubmit(e){
console.log("Trying To log in");
axios
.post(`${api_url}/promotor/login`,{username: this.state.username, password:this.state.password})
.then( (res) => {
if (res.status === 200) {
console.log(res);
this.setState(() => ({toClientHome: true, id:res.data.id}));
}
});
e.preventDefault();
}
Axios 请求访问受保护的 GET 请求
(设置会话cookie时GET请求在邮递员中有效,但不适用于axios)
getFullName(id) {
axios
.get(`${api_url}/promotor/name/${id}`,{
withCredentials: true
})
.then((res) => {
//... rest of the code
});
}
【问题讨论】:
-
我推荐使用令牌系统进行身份验证,而不是基于 cookie 的会话。 JWT 目前是一个不错的选择。
-
@DatTran 是的,在搜索答案时,我了解到 JWT 可能是比我目前使用的基于会话的方法更好的解决方案。感谢您的建议!
标签: reactjs passport.js axios express-session