【发布时间】:2018-03-08 17:42:55
【问题描述】:
在身份验证方面,我完全是新手。我正在尝试将 Colt Steele 使用的方法作为他的web developer's bootcamp course 的一部分来适应我的项目。
Colt 使用 Node.js + Express.js + MongoDB,在 ejs 中进行服务器端渲染。对于用户身份验证,他使用 Passport.js。
我正在使用 Node.js + Express.js + MongoDB 和 React.js 进行客户端渲染。我也使用反应路由器。我也在尝试使用 Passport 对用户进行身份验证。
我的问题是,虽然我可以成功登录,但我仍然无法访问登录墙后面的任何内容。当我向服务器发出请求以检查用户是否经过身份验证的某个路由时,答案总是错误的。
这是我的验证码。
const express = require("express"),
server = express(),
path = require("path"),
mongoose = require("mongoose"),
User = require("./models/User"),
bodyParser = require("body-parser"),
passport = require("passport"),
localStrategy = require("passport-local"),
passportLocalMongoose = require("passport-local-mongoose"),
expressSession = require("express-session");
mongoose.connect("mongodb://localhost/diary");
server.use(
bodyParser.urlencoded({
extended: true
})
);
//Auth
server.use(
expressSession({
secret: "This is pretty damn weird.",
resave: false,
saveUninitialized: false
})
);
server.use(passport.initialize());
server.use(passport.session());
passport.use(new localStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
// Auth login
server.post("/login", function(request, response) {
passport.authenticate("local", function(err, user, info) {
if (err) {
return console.log(err);
}
if (!user) {
return response.send(false);
}
request.logIn(user, function(err) {
if (err) {
return console.log(err);
}
checkLogIn(request, response);
return response.send(true);
});
})(request, response);
});
//Auth checkLogIn
function checkLogIn(request, response) {
if (request.isAuthenticated()) {
return console.log("authenticated");
} else {
return console.log("not authenticated");
}
}
由于我使用的是客户端渲染,我无法使用 response.redirect 将用户重定向到任何地方。这就是我使用 response.send(true)(或 false)的原因:我使用它们作为标志来告诉 React 应用程序该做什么。
上面的代码与 Colt 的代码几乎相同:他将 expressSession 的配置保持在最低限度,并且似乎没有定义自己的本地策略或(反)序列化函数。在我发现的几个教程中,每个人似乎都这样做,但 Colt 没有,而且他的应用程序运行得很好。他也不使用任何 MongoStore,很多其他人似乎都这样做。
如您所见,我在 request.logIn 之后调用了一个 checkLogIn 函数,它只是 console.logs 用户是否登录。登录后,它在屏幕上打印 true,即登录确实成功.
此时我应该已经登录,但是如果我尝试从浏览器访问受保护的部分,我会被告知我没有登录。例如,我以假用户 Elmo 成功登录,然后尝试访问/elmo/diary。这会将我带到一个 React 组件,该组件在特定路由上查询服务器,这个:
//Find all entries of a given user.
router.get("/entries/:userURL", isLoggedIn, (request, response) => {
console.log("get entries");
User.findOne(
{ customURL: request.params.userURL },
{ entryIDs: 1 },
(err, data) => {
//Get the actual entries.
Entry.find({ _id: { $in: data.entryIDs } }, (err, entries) => {
if (err) {
console.log(err);
} else {
response.send(entries);
}
});
}
);
});
如您所见,我使用了一个 isLoggedIn 中间件,如下所示:
//Auth isLoggedIn
function isLoggedIn(request, response, next) {
console.log(request);
if (request.isAuthenticated()) {
console.log("logged in");
return next();
}
console.log("not logged in");
return (function() {
response.send(false);
})();
}
所以如果我以 Elmo 身份登录,上面的路由应该会返回数据。但是,无论我是否登录,中间件都会返回 false。
我检查了我的 localhost 的 cookie,应用程序在其中运行,只有一个具有令牌外观的值 (s%3Ak0SZJ97eJkPjqjE6jC-azn7y3ztK2UMw.fYOfM9324JUIeUDGvh26swEWwMf3j3HDUmh9WubNF%2B8),所以我猜 Passport 正在创建会话并存储它在cookie中成功。
说实话,我也不确定这个系统对 Colt 是如何工作的,因为他的前端似乎没有发回任何令牌/数据供后端检查,而我(诚然有限)的理解是不是应该是这样的。
知道我做错了什么吗?
【问题讨论】:
-
客户端路由,你用的是react-router还是express?
-
@Dream_Cap 反应路由器。
标签: node.js reactjs authentication cookies passport.js