如何在Next.js、MongoDB和bcrypt中实现简单且相对安全的密码验证?

huangapple go评论73阅读模式
英文:

How would I implement an easy and somewhat save password-authentification with next.js, mongoDB and bcrypt?

问题

我是一位业余程序员,不需要为我的项目使用行业标准。但是,我想在我的next.js项目中实现一个相对安全的密码验证,仅使用我的next.js后端API和MongoDB(通过Data API连接Atlas)来实现这个目的。

我知道有不同的第三方身份验证流程可用,甚至有更安全的选项。因此,我想强调我正在寻找更低级别的解决方案。

我的基本设置是将用户数据(包括用户名和经过bcrypt加密的密码)存储在我的数据库中。现在,当用户输入其登录数据时,我不确定应该如何进行。在某个时候,我必须执行 bcrypt.compare(password, hashedPassword) 来验证密码。然而,在我理解中,我要么必须将已散列的密码发送到我的前端(这感觉不对),要么通过HTTP请求将密码作为纯文本发送到后端(这也感觉不对)。客户端对密码进行散列是不可能的,因为使用盐(例如 bcrypt.hash(password, 10) ),我无法比较两个已散列的字符串。

有人能简单地解释一下在这种设置下如何最好地比较密码吗?

英文:

I am a hobby programmer and don't need an industry-standard for my project. However, I would like to implement a reasonably secure password authentication in my next.js project and only use my next.js backend API and a MongoDB (Atlas via Data API) for this purpose.

I am aware that there are different 3rd-party authentication processes available and that there are even more secure options. Therefore, I want to emphasize that I am looking for something on a lower level.

My basic setup is that user data with names and passwords (bcrypt encrypted) are stored in my database. Now, when the user enters their login data, I'm not sure how to proceed. At some point, I have to execute bcrypt.compare(password, hashedPassword) to verify the password. However, in my understanding, I either have to send the hashed password to my frontend (which feels wrong) or send the password as plain text to the backend via an HTTP request (which also feels wrong). Client-side hashing of the password is not possible because, with the use of salt (e.g. bcrypt.hash(password, 10)), I cannot compare two hashed strings.

Can someone explain to me in simple terms how to best approach comparing passwords in this setup?

答案1

得分: 1

你没有向客户端发送任何凭据。你在服务器上处理一切。

你将用户输入(电子邮件、密码等)发送到服务器。服务器首先必须验证这些值。然后在服务器上从数据库中获取用户。

// 你首先验证了 req.body 数据
let user = await User.findOne({ email: req.body.email });
if (!user) return res.status(400).send("无效的密码或电子邮件");

user 包含用户数据。我假设用户注册时已经对密码进行了哈希处理。

当你从客户端向服务器发送数据时,你是通过 https 发送的,而不是明文。这些数据通过 tls 协议 进行加密。

需要注意的是,TLS 不保护端系统上的数据。它只是确保通过互联网安全传递数据,避免可能的窃听和/或内容更改。

英文:

you are not sending any credentials to the client. you handle everything on the server.

you send user inputs (email,password,etc) to the server. server first has to validate those values. then on server you get the user from the db.

// you validated the req.body data first
let user = await User.findOne({ email: req.body.email });
if (!user) return res.status(400).send("invalid password or email");

user holds the user data. I am assuming you already hashed the password when a user signs up.

const validPassword = await bcrypt.compare(req.body.password, user.password);
if (!validPassword) return res.status(400).send("invalid email or password");

when you send data from client to server, you are sending over https it is not plain text. that data is encrypted by tls protocol

> It should be noted that TLS does not secure data on end systems. It
> simply ensures the secure delivery of data over the Internet, avoiding
> possible eavesdropping and/or alteration of the content.

huangapple
  • 本文由 发表于 2023年5月14日 02:15:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/76244254.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定