javascript - 如何在节点 js express 中添加密码检查中间件
问题描述
我正在尝试制作一个中间件,该中间件显示一个要求输入密码以输入路由的表单。
问题是我在获取路由中,我无法在获取请求中传递数据,因为我不想在 url 中传递密码。因此,我尝试制作一个中间件,该中间件显示一个带有隐藏信息的表单,例如客户想要访问的聊天的 id 提交到另一条路线(帖子)。在发布路线中,它会检查密码是否正确以及是否返回原始路线(获取)并显示聊天。
这是我到目前为止所做的:
GET 路线:
router.get('/chats/:id', middleware.isLoggedIn, middleware.isAllowed, catchAsync(async (req, res, next) => {
const foundChat = await Chat.findOne({
_id: req.params.id
})
console.log('here', foundChat)
res.render('chat/show', {
chat: foundChat
})
}))
POST 路线
router.post('/chats/password', middleware.askForPassword)
中间件
middleware.isAllowed = async function (req, res, next) {
if (req.cookies.allowed) {
if (req.cookies.allowed.includes(req.params.id)) {
req.body.password = null
return next()
}
} else {
res.redirect('/chats/password')
}
}
middleware.askForPassword = async function (req, res, next) {
try {
const hashedDBPassword = await Chat.findById(req.params.id)
const password = req.body.password
const passwordHashed = hashedDBPassword.password
const cookieName = encodeURIComponent(hashedDBPassword.name)
const resultCompare = await bcrypt.compare(password, passwordHashed)
let value
if (req.cookies.allowed === undefined) {
res.cookie('allowed', [], {
maxAge: 30000,
httpOnly: true
})
}
if (resultCompare === true) {
value = req.cookies.allowed
value.push(passwordHashed)
res.cookie('allowed', value, {
maxAge: 30000,
httpOnly: true
})
res.redirect('/chats/' + req.body.id)
} else {
global.nextMiddleware = true
res.render('chat/password', {
id: req.body.id
})
}
} catch (err) {
console.log(err)
res.redirect('/chats')
}
}
表格
<% layout("layouts/boilerplate.ejs") %>
<form action="/chats/password" method="post">
<input type="password" name="password" id="password">
<input type="hidden" name="id" value="<%= id %>">
<input type="submit" value="Go!">
</form>
解决方案
如果您希望您的代码是 RESTful 的,那么路由可能如下所示:
POST /auth
GET /auth
GET /auth/:sessionId
DELETE /auth/:sessionId
GET /chat/:chatId
方法POST /auth
,应该设置授权cookie并返回sessionId
给客户端。客户端可以放入sessionId
localStorage。也可以有可选参数redirect,可以将成功的请求重定向到指定的URL。但是您应该谨慎使用它,并且不允许重定向到外部主机。
方法GET /auth
列出当前用户打开的所有实时会话。当您需要关闭其他设备上的会话时,它可能会有所帮助。
方法GET /auth/:sessionId
通过其 ID 返回会话。它可以包含有关会话的信息,例如上次活动、设备(浏览器或移动设备)等。
方法从路由DELETE /auth/:sessionId
接收sessionId
,使用授权 cookie 验证会话所有权,在 DB 中标记会话已关闭(如果您将会话存储在 DB 中),并删除授权 cookie。
方法GET /chat/:chatId
仅依赖于 HTTP 授权 cookie(像现在一样工作)。
您可以通过 XHR 从前端发送 POST 请求,收到成功的响应,然后导航到聊天。
推荐阅读
- winapi - Windows:使用 FreePascal 调用 WMI 函数——工作示例?
- excel - 小计更改时触发事件(excel、vba)
- wpf - WPF 用户控件作为多边形
- spring-data-jpa - 如何减少 Atomikos 中的 getConnection 时间消耗
- node.js - 请解释在使用 .then() 和 Promise 时调用语法的细微差别的巨大影响
- azerothcore - 如何安装 azerothcore 模块,例如缓冲区 npc 模块
- c++ - DLL 项目未在 Visual Studio 2019 中构建
- python - 使用pytest测试同一个类的不同实例
- r - 将矩阵转换为分配特定列的数组
- javascript - 嵌套在函数内的异步函数