Node.js登录接口实现密码错误次数限制与账户锁定
本文详解在Node.js登录接口中实现密码错误尝试次数限制的方法。通过数据库记录失败日期与次数,结合Crypto模块进行MD5双重加密,当错误次数超过阈值时锁定账户并返回提示,有效防止暴力破解,保障用户账户安全。
Node.js登录接口实现密码错误次数限制与账户锁定
限制密码尝试次数能够有效保护用户账户安全。即使面对量子计算机等强大算力,这种限制机制也能使其难以突破。
这一机制类似于银行卡账户,当尝试次数过多时,系统会自动锁定账户,甚至可能触发自动报警功能。
具体效果如下图所示。
实现思路与数据库设计
实现思路如下。
首先需要设计数据库表结构。
在数据库表中添加一个字符串类型的字段,用于存储两个关键数据:密码失败尝试日期和尝试次数,格式参考 2019a10a23|10。此处使用竖线“|”作为数据段的分割符,字母“a”作为日期各部分的分割符。
代码逻辑与封装
接下来梳理代码逻辑。
如果记录的日期与当天相同,则在密码输入错误时,执行 次数+1 操作。
如果记录的日期不是当天,则重置相关计数。
将上述逻辑封装为独立模块。
以下是实现该功能的简化代码封装。
该示例仅实现了一天内的简单次数校验,更高级的规则需要根据实际需求自行修改。
/**
* 尝试登录次数限制
* login_number [日期, 次数].join('|')
* 更新到数据库 (更新数据) => {}
* return {
* run bool true: 超过 false: 正常
* start 登录失败后修改状态
* }
*/
exports.Login_n = (login_number, 更新到数据库) => {
let run = true
let 当日登录次数 = 0
let 当日最多尝试次数 = 10
var getD = () => {
var date = new Date()
var d = [date.getUTCFullYear(), date.getMonth() + 1, date.getDate()].join('a')
return d
}
if(login_number){
let date = login_number.split('|')[0]
let n = login_number.split('|')[1]
if(date == getD()){
当日登录次数 = (+n)
}
}
if(当日登录次数 >= 当日最多尝试次数){
run = false
}
let 登录失败后修改状态函数 = () => {
let add_login_number
let 非当日 = () => {
更新到数据库([getD(), 0].join('|'))
}
let 今天 = (n) => {
更新到数据库([getD(), n].join('|'))
}
if(!login_number){
非当日()
}else{
let date = login_number.split('|')[0]
let n = login_number.split('|')[1]
if(date == getD()){
今天((+n) + 1)
}
}
}
return {
run,
start: 登录失败后修改状态函数
}
}
使用示例与完整代码
具体使用方式如下。
首先引入模块并设置状态。
var { Login_n } = require('./login_n')
var login_n = Login_n(login_number, (v) => {
db('all', 'update t_user set login_number=? where id=?', [v, id]).then(results => {
console.log('修改登录失败次数记录成功')
})
})
在请求拦截阶段进行检查。
if(!login_n.run){
resolve({
code: 1,
msg: '账户异常锁定, 请明天再试'
})
return
}
当密码错误时,开始记录失败状态。
if(results[0].pw !== pw){
// 登录失败,更新登录次数
login_n.start()
resolve({
code: 1,
msg: '密码错误'
})
return
}
完整的登录代码实现如下。
需要引入上述实现的错误限制次数代码模块。
此处使用MD5算法进行双重加密,目的是即使内部员工获取了数据库中的密码哈希值,也难以直接登录。该功能依赖Node.js内置的 crypto 模块。
var crypto = require('crypto')
exports.phone_pw_login = (params, req) => new Promise((resolve, reject) => {
var { Login_n } = require('./login_n')
let {pass, phone} = params
var md5 = crypto.createHash("md5");
let pw = md5.update(pass).digest('hex').toUpperCase()
db('all', 'SELECT phone, pw, id, name, login_number from t_user WHERE phone=?', [phone]).then(results => {
let { login_number, id } = results[0]
// 账号不存在
if(results.length == 0){
resolve({
code: 1,
msg: '密码错误', // 避免得知是否注册账号
})
return
}
// 次数校验
var login_n = Login_n(login_number, (v) => {
db('all', 'update t_user set login_number=? where id=?', [v, id]).then(results => {
console.log('修改登录失败次数记录成功')
})
})
if(!login_n.run){
resolve({
code: 1,
msg: '账户异常锁定, 请明天再试'
})
return
}
if(results[0].pw !== pw){
// 登录失败,更新登录次数
login_n.start()
resolve({
code: 1,
msg: '密码错误'
})
return
}
let token = Jwt.Create({phone: results[0].phone, id: id, pw})
resolve({
code: 200,
msg: {
name: results[0].name,
phone: results[0].phone,
token,
}
})
})
.catch(error => {
console.log(error)
resolve({
code: 1,
msg: '服务器错误'
})
})
})
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。
Node.js中使用path模块获取文件名
2026-11-05 15:15:15
Node.js中url模块与querystring模块处理查询字符串的区别
2026-11-05 15:04:45
JavaScript(JS)主要用来做什么
2026-11-05 10:10:47
怎么修改Node.js和npm的全局安装路径与缓存目录
2026-11-04 19:48:28
NW.js 常见问题排查:Node 模块加载失败与版本兼容解决
2026-11-04 11:22:45
