如何使用 React MongoDB 和 Express 正确加密和解密密码
How to properly encrypt and decrypt passwords using React MongoDB and Express
目前我在本地机器上的开发环境中工作,我使用 MongoDB 以纯文本形式存储密码。我使用 express-jwt
和 jsonwebtoken
来传递用户数据和身份验证。我已经研究了 bcryptjs
和 bcrypt
并且我想实现最适合 React 和 Express 的那个,以便将散列密码从客户端传递到数据库。我找到了服务器端的资源,但没有找到客户端的资源。
那么我的问题是,当密码从客户端传递时,将加密密码正确保存在我的服务器上的方法是什么?如何在客户端加密密码然后验证服务器端?
我看过一些文章说由于 ssl 不需要加密客户端,但其他人说绝对需要加密客户端。什么是正确的方法,我该如何在我的 React 应用程序上实现它?
您没有解密密码。您向用户询问密码,然后对其进行哈希处理并将其与您保存的存储哈希值进行比较。如果它们相同,那么(假设您有安全的哈希算法)未加密的版本也必须相同。
使用 Bcryptjs、Express 和 MongoDB:
客户端无需加密,您可以使用 post 请求(通常通过表单)将密码以纯文本形式传递给服务器。
假设您有一个类似于此的 'user' 架构:
const userSchema = new mongoose.Schema({
email:{type:String,required:true,unique:true},
password:{type:String,required:true}
},{collection:'users'}
const User= mongoose.model("User",userSchema);
)
在服务器 register/sign 上,你处理请求的地方你会散列用户的密码,如下所示:
app.post('/signup',async (req,res)=>{
// geting our data from frontend
const {email,password:plainTextPassword}=req.body;
// encrypting our password to store in database
const password = await bcrypt.hash(plainTextPassword,salt);
try {
// storing our user data into database
const response = await User.create({
email,
password
})
return res.redirect('/');
} catch (error) {
console.log(JSON.stringify(error));
if(error.code === 11000){
return res.send({status:'error',error:'email already exists'})
}
throw error
}
})
4.Upon 登录请求(也将是通过客户端表单的 post),您将使用 bcrpyt.compare() 函数比较密码,如果成功,像这样为用户分配一个 JWT,此方法假定令牌将存储在 Cookies 中。
const verifyUserLogin = async (email,password)=>{
try {
const user = await User.findOne({email}).lean()
if(!user){
return {status:'error',error:'user not found'}
}
if(await bcrypt.compare(password,user.password)){
// creating a JWT token
token = jwt.sign({id:user._id,username:user.email,type:'user'},JWT_SECRET,{ expiresIn: '2h'})
return {status:'ok',data:token}
}
return {status:'error',error:'invalid password'}
} catch (error) {
console.log(error);
return {status:'error',error:'timed out'}
}
}
// login
app.post('/login',async(req,res)=>{
const {email,password}=req.body;
// we made a function to verify our user login
const response = await verifyUserLogin(email,password);
if(response.status==='ok'){
// storing our JWT web token as a cookie in our browser
res.cookie('token',token,{ maxAge: 2 * 60 * 60 * 1000, httpOnly: true }); // maxAge: 2 hours
res.redirect('/');
}else{
res.json(response);
}
})
- 前端我没有讲,因为在react中只包含基本的POST请求表单,不需要在client-side上做任何特殊的方法或处理。
希望对你有帮助。
编辑、散列client-side:
对此存在争议,在某些协议中,甚至需要在 client-side 上散列密码,简而言之,因为 SSL 已经加密了从客户端移动到服务器的所有内容 client-side 上的散列非常漂亮毫无意义,今天没有被广泛接受,即使是@大公司也是如此。最重要的是,增加的安全性可以忽略不计,不值得麻烦和向客户端公开散列逻辑
目前我在本地机器上的开发环境中工作,我使用 MongoDB 以纯文本形式存储密码。我使用 express-jwt
和 jsonwebtoken
来传递用户数据和身份验证。我已经研究了 bcryptjs
和 bcrypt
并且我想实现最适合 React 和 Express 的那个,以便将散列密码从客户端传递到数据库。我找到了服务器端的资源,但没有找到客户端的资源。
那么我的问题是,当密码从客户端传递时,将加密密码正确保存在我的服务器上的方法是什么?如何在客户端加密密码然后验证服务器端?
我看过一些文章说由于 ssl 不需要加密客户端,但其他人说绝对需要加密客户端。什么是正确的方法,我该如何在我的 React 应用程序上实现它?
您没有解密密码。您向用户询问密码,然后对其进行哈希处理并将其与您保存的存储哈希值进行比较。如果它们相同,那么(假设您有安全的哈希算法)未加密的版本也必须相同。
使用 Bcryptjs、Express 和 MongoDB:
客户端无需加密,您可以使用 post 请求(通常通过表单)将密码以纯文本形式传递给服务器。
假设您有一个类似于此的 'user' 架构:
const userSchema = new mongoose.Schema({ email:{type:String,required:true,unique:true}, password:{type:String,required:true} },{collection:'users'} const User= mongoose.model("User",userSchema); )
在服务器 register/sign 上,你处理请求的地方你会散列用户的密码,如下所示:
app.post('/signup',async (req,res)=>{
// geting our data from frontend
const {email,password:plainTextPassword}=req.body;
// encrypting our password to store in database
const password = await bcrypt.hash(plainTextPassword,salt);
try {
// storing our user data into database
const response = await User.create({
email,
password
})
return res.redirect('/');
} catch (error) {
console.log(JSON.stringify(error));
if(error.code === 11000){
return res.send({status:'error',error:'email already exists'})
}
throw error
}
})
4.Upon 登录请求(也将是通过客户端表单的 post),您将使用 bcrpyt.compare() 函数比较密码,如果成功,像这样为用户分配一个 JWT,此方法假定令牌将存储在 Cookies 中。
const verifyUserLogin = async (email,password)=>{
try {
const user = await User.findOne({email}).lean()
if(!user){
return {status:'error',error:'user not found'}
}
if(await bcrypt.compare(password,user.password)){
// creating a JWT token
token = jwt.sign({id:user._id,username:user.email,type:'user'},JWT_SECRET,{ expiresIn: '2h'})
return {status:'ok',data:token}
}
return {status:'error',error:'invalid password'}
} catch (error) {
console.log(error);
return {status:'error',error:'timed out'}
}
}
// login
app.post('/login',async(req,res)=>{
const {email,password}=req.body;
// we made a function to verify our user login
const response = await verifyUserLogin(email,password);
if(response.status==='ok'){
// storing our JWT web token as a cookie in our browser
res.cookie('token',token,{ maxAge: 2 * 60 * 60 * 1000, httpOnly: true }); // maxAge: 2 hours
res.redirect('/');
}else{
res.json(response);
}
})
- 前端我没有讲,因为在react中只包含基本的POST请求表单,不需要在client-side上做任何特殊的方法或处理。 希望对你有帮助。
编辑、散列client-side: 对此存在争议,在某些协议中,甚至需要在 client-side 上散列密码,简而言之,因为 SSL 已经加密了从客户端移动到服务器的所有内容 client-side 上的散列非常漂亮毫无意义,今天没有被广泛接受,即使是@大公司也是如此。最重要的是,增加的安全性可以忽略不计,不值得麻烦和向客户端公开散列逻辑