ReactJS如何实现5次登录尝试后锁定用户及注册密码校验功能
功能实现方案
1. 登录账号锁定功能
- 后端逻辑调整:
- 用户表新增
login_fail_countint类型字段,默认值为0,用于记录当前账号连续输错密码的次数 - 登录接口逻辑优化:
- 优先查询对应用户名的账号,若
isBlock字段为true,直接返回账号锁定标识 - 密码校验失败时,将
login_fail_count数值+1,当数值达到5时,将isBlock字段设为true - 密码校验成功时,将
login_fail_count重置为0
- 优先查询对应用户名的账号,若
- 用户表新增
- 前端逻辑调整:
- 在
login请求的回调中新增锁定状态判断,后端返回锁定标识时,将提示信息设置为user block
- 在
2. 注册密码校验功能
- 修正原有正则错误:原有
checkUppercase方法的正则/[A-Z][a-z]/只能匹配大写后接小写的连续字符,不符合「至少存在1个英文字符」的要求,修改为/[a-zA-Z]/ - 注册点击前置校验:在
signUp方法最前面先判断三个密码校验状态是否全部为true,不满足则直接提示密码规则,不向后端发送注册请求 - 注册按钮禁用逻辑优化:只有账号密码非空且三个密码校验全部通过时,注册按钮才可点击
完整修改后代码
import './App.css'; import * as React from "react"; import Cookies from "universal-cookie"; import axios from "axios"; class LoginPage extends React.Component { state = { username: "", password: "", isBlock:false, showError: false, response: "", passwordLengthValid: false, letterValid: false, numberValid: false } resetForm = () => { this.setState({ username: '', password: '', response: '' }) } // 校验密码长度 checkPasswordLength = (password) => { this.setState({ passwordLengthValid: password.length >= 6 }) } // 校验是否包含英文字符 checkLetter = (password) => { const pattern = /[a-zA-Z]/; this.setState({ letterValid: pattern.test(password) }) } // 校验是否包含数字 checkNumber = (password) => { const pattern = /[0-9]/; this.setState({ numberValid: pattern.test(password) }) } onUsernameChange = (event) => { this.setState({ username: event.target.value }) } onPasswordChange = (event) => { const pwd = event.target.value this.setState({ password: pwd }) this.checkPasswordLength(pwd); this.checkLetter(pwd); this.checkNumber(pwd); }; login = () => { axios.get("http://localhost:8989/sign-in", { params: { username: this.state.username, password: this.state.password } }) .then((response) => { // 账号锁定判断 if (response.data.block) { this.setState({ response: "user block", showError: true }) return } if (response.data && response.data.length > 0 ) { const cookies = new Cookies(); cookies.set("logged_in", response.data); window.location.reload(); } else { this.setState({ showError: true, response: "用户名或密码错误" }) } }) } signUp = () => { // 注册前置密码校验 const {passwordLengthValid, letterValid, numberValid} = this.state if (!passwordLengthValid || !letterValid || !numberValid) { this.setState({ showError: true, response: "密码需满足:长度不少于6位,包含数字和至少1个英文字符" }) return } axios.get("http://localhost:8989/create-account", { params: { username: this.state.username, password: this.state.password, isBlock:this.state.isBlock } }) .then((response) => { if (response.data) { this.setState({ response: "Your account has been created!" }) } else { this.setState({showError: true, response: "This username is already taken"}) } }) } render() { const inputStyle = { margin: "10px", width: "200px" } const buttonStyle = { margin: "10px", width: "200px", backgroundColor: "black", color: "white", borderRadius: "5px" } const signUpButtonStyle = { margin: "10px", width: "200px", backgroundColor: "green", color: "white", borderRadius: "5px", marginTop: "20px" } const hasRequiredDetails = !(this.state.username == "" || this.state.password == ""); const passwordValid = this.state.passwordLengthValid && this.state.letterValid && this.state.numberValid; return ( <div style={{margin: "auto", width: "50%", padding: "10px"}}> <fieldset style={{width: "300px"}}> <legend> <div style={{fontSize: "20px"}}> Login to your account </div> </legend> <input style={inputStyle} onChange={this.onUsernameChange} value={this.state.username} placeholder={"Enter username"} /> <input type={"password"} style={inputStyle} onChange={this.onPasswordChange} value={this.state.password} placeholder={"Enter password"} /> <div> <button style={buttonStyle} onClick={this.login} disabled={!hasRequiredDetails} >Login</button> </div> <div> <button style={signUpButtonStyle} onClick={this.signUp} disabled={!hasRequiredDetails || !passwordValid} >Sign Up</button> </div> <div> <button className="button--secondary" onClick={this.resetForm}> Reset </button> </div> </fieldset> <div style={{color: "red"}}>{this.state.response}</div> </div> ) } } export default LoginPage;
内容的提问来源于stack exchange,提问作者Floziko
相关产品推荐
相关产品推荐

