我正在开发一个简单的网站,它支持基于本地JSON文件的登录和注销功能,该文件包含用户列表和散列密码。我正在使用快速会话为我的cookie跟踪用户是否已成功登录服务器端并表示为我的服务器。
在我的登录页面上,我呈现login.handlebars视图。如果用户使用匹配的凭据成功登录,则页面将重新路由到/ private。目前,如果用户未输入匹配的登录凭据,则页面将刷新。
如果用户尝试使用不正确的凭据登录,我需要重新呈现/刷新同一页面,这次仅使用401状态代码,并在页面上显示错误消息。
这是我到目前为止在服务器端的登录路径中的内容:
router.get("/", async (req, res) => {
res.render("login/login")
})
router.post("/", async (req, res) => {
// Check if user name is in users
for(let i=0; i < users.length; i++){
// If the user name is valid and found in the data base
if(users[i].username === req.body.username){
// Compare the passwords of the user to the hashedPassword that is stored
let hashcmp = await bcrypt.compare(req.body.password, users[i].hashedPassword)
if(hashcmp){
// Set the cookie and authenticate the login
console.log("Correct user name and password, setting AuthCookie")
req.session.userId = String(users[i]._id)
req.session.loggedin = true
// Redirect to private
res.redirect("/private")
return
}
// If the passwords dont match --> break the loop
else{
break
}
}
}
// Otherwise redirect to get /login
// TODO: Re-render page with error message and 401 status code
res.redirect("/login")
return
})
实现这一目标的最佳/最理想的解决方案是什么?如果另外需要重新呈现页面,如何在实际操作中使用登录页面完成此操作?
你可以使用connect-flash。它是Express的Flash消息中间件。我建议你仔细阅读一下。
闪存是用于存储消息的会话的特殊区域。消息被写入闪存并在显示给用户后被清除。闪存通常与重定向结合使用,确保消息可用于要呈现的下一页。
首先,在你的app.js
文件中,需要这个模块const flash = require('connect-flash');
然后,在同一文件中和路由定义之前,添加此代码
app.use(flash());
// Add errors on locals.
app.use(function (req, res, next) {
res.locals.errors = req.flash("error");
next();
});
res.locals
是一个对象,它包含可用于下一个渲染视图的响应局部变量。
接下来,在控制器中,在res.redirect("/login")
之前,在locals对象中添加您的错误消息。
// Otherwise redirect to get /login
// TODO: Re-render page with error message and 401 status code
req.flash("error", "User does not exist.");
res.redirect("/login")
最后一件事就是在登录视图中添加errors
。我不确定把手,但在ejs
文件中我使用这个:
<div>
<% errors.forEach(function (error) { %>
<p><%= error %></p>
<% }) %>
</div>
也许在车把中你可以使用这样的东西
<div>
{{#each errors}}
<p>{{this}}</p>
{{/each}}
</div>
同样,你应该阅读connect-flash
的工作原理以及你可以用这个模块做些什么。它对于不同类型的消息非常有用,而不仅仅是错误消息。
这很简单。只需使用res.render
通过传递错误消息来呈现所需的页面
// Otherwise redirect to get /login
// TODO: Re-render page with error message and 401 status code
res.status(401).render("login/login", { error: "Opps!" })
return
在你看来有一个条件:
<div class="error">
{{#if error}}
<p>{{error}}</p>
{{/if}}
</div>