You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ReactJS如何实现5次登录尝试后锁定用户及注册密码校验功能

功能实现方案

1. 登录账号锁定功能

  • 后端逻辑调整:
    • 用户表新增login_fail_count int类型字段,默认值为0,用于记录当前账号连续输错密码的次数
    • 登录接口逻辑优化:
      1. 优先查询对应用户名的账号,若isBlock字段为true,直接返回账号锁定标识
      2. 密码校验失败时,将login_fail_count数值+1,当数值达到5时,将isBlock字段设为true
      3. 密码校验成功时,将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 06:06:04