ホームページ  >  記事  >  バックエンド開発  >  PHPログイン失敗時の対処法

PHPログイン失敗時の対処法

藏色散人
藏色散人オリジナル
2021-03-19 09:14:384379ブラウズ

PHP ログイン失敗の処理方法: まず、ユーザーのログイン情報を記録するテーブルを作成し、次に user_login_info テーブルをクエリして、過去 30 分間に関連するパスワード エラーの記録があるかどうかを確認し、合計がレコード数が設定値に達する 一定のエラー数; 最後に、ログイン パスワードのエラー数に制限を設定します。

PHPログイン失敗時の対処法

#この記事の動作環境: Windows7 システム、PHP7.1 バージョン、DELL G3 コンピューター

PHP はログイン失敗制限を実装しています

間違ったログイン パスワードの数の制限

すべての Web サイトにとってセキュリティの重要性は自明のことです。中でもログインはWebサイト内でより攻撃を受​​けやすい箇所ですが、ログイン機能のセキュリティを強化するにはどうすればよいでしょうか?

まず、いくつかの有名な Web サイトがどのように行うかを見てみましょう

Github

Github Web サイト上の同じアカウントは、同じ IP アドレスを使用して、パスワードを連続して入力すると、一定回数間違えるとアカウントが30分間ロックされます。

Github がこれを行う主な理由は、主に次の考慮事項に基づいていると思います:

ユーザーのアカウントのパスワードが暴力的に解読されるのを防ぐ

実装アイデア

多くのWebサイトのログイン機能にこの機能があるので、具体的にどのように実装するか。以下で詳しく説明しましょう。

アイデア

ログインが成功したか失敗したかにかかわらず、ユーザーのログイン情報を記録するにはテーブル (user_login_info) が必要です。また、ログインが失敗したか成功したかを区別できる必要があります。

ログインするたびに、最初に、過去 30 分間に関連するパスワード エラーの記録があるかどうかを user_login_info テーブルからクエリします (ここでは、パスワード エラーの数が 5 回に達すると、ユーザーは30 分間無効化) を実行し、合計レコード数をカウントします。項目数が設定されたエラー数に達しているかどうかを確認します。

同じ IP の同じユーザーが 30 分以内に間違ったパスワードの回数が設定された回数に達すると、そのユーザーはログインできなくなります。

[推奨:

PHP ビデオ チュートリアル ]

具体的なコードとテーブルの設計

テーブルの設計

user_login_info テーブル

   CREATE TABLE `user_login_info` (
       `id` int(10) UNSIGNED PRIMARY KEY AUTO_INCREMENT  NOT NULL,
       `uid` int(10) UNSIGNED NOT NULL,
       `ipaddr` int(10) UNSIGNED NOT NULL COMMENT '用户登陆IP',
       `logintime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP 
       COMMENT '用户登陆时间',
       `pass_wrong_time_status` tinyint(10) UNSIGNED NOT NULL COMMENT '登陆密码错误状态' 
       COMMENT '0 正确 2错误'
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
user表(用户表)
   CREATE TABLE `user` (
      `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
      `name` varchar(100) NOT NULL COMMENT '用户名',
      `email` varchar(100) NOT NULL,
      `pass` varchar(255) NOT NULL,
      `status` tinyint(3) UNSIGNED NOT NULL DEFAULT '1' COMMENT '1启用 2禁用',
       PRIMARY key(id)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
核心代码
<?php
 
class Login
{
 
    protected $pdo;
 
    public function __construct()
    {
        //链接数据库
        $this->connectDB();
    }
 
    protected function connectDB()
    {
        $dsn = "mysql:host=localhost;dbname=demo;charset=utf8";
        $this->pdo = new PDO($dsn, &#39;root&#39;, &#39;root&#39;);
    }
 
    //显示登录页
    public function loginPage()
    {
          include_once(&#39;./html/login.html&#39;);
 
    }
 
    //接受用户数据做登录
    public function handlerLogin()
    {
 
        $email = $_POST[&#39;email&#39;];
        $pass = $_POST[&#39;pass&#39;];
 
        //根据用户提交数据查询用户信息
        $sql = "select id,name,pass,reg_time from user where email = ?";
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute([$email]);
 
        $userData = $stmt->fetch(\PDO::FETCH_ASSOC);
 
        //没有对应邮箱
        if ( empty($userData) ) {
 
            echo &#39;登录失败1&#39;;
 
            echo &#39;<meta http-equiv="refresh" content="2;url=./login.php">&#39;;
            exit;
        }
 
        //检查用户最近30分钟密码错误次数
        $res = $this->checkPassWrongTime($userData[&#39;id&#39;]);
 
        //错误次数超过限制次数
        if ( $res === false ) {
            echo &#39;你刚刚输错很多次密码,为了保证账户安全,系统已经将您账号锁定30min&#39;;
 
            echo &#39;<meta http-equiv="refresh" content="2;url=./login.php">&#39;;
            exit;
        }
 
 
        //判断密码是否正确
        $isRightPass = password_verify($pass, $userData[&#39;pass&#39;]);
 
        //登录成功
        if ( $isRightPass ) {
 
            echo &#39;登录成功&#39;;
            exit;
        } else {
 
            //记录密码错误次数
            $this->recordPassWrongTime($userData[&#39;id&#39;]);
 
            echo &#39;登录失败2&#39;;
            echo &#39;<meta http-equiv="refresh" content="2;url=./login.php">&#39;;
            exit;
        }
 
    }
 
    //记录密码输出信息
    protected function recordPassWrongTime($uid)
    {
 
        //ip2long()函数可以将IP地址转换成数字
        $ip = ip2long( $_SERVER[&#39;REMOTE_ADDR&#39;] );
 
        $time = date(&#39;Y-m-d H:i:s&#39;);
        $sql = "insert into user_login_info(uid,ipaddr,logintime,pass_wrong_time_status) values($uid,$ip,&#39;{$time}&#39;,2)";
 
 
        $stmt = $this->pdo->prepare($sql);
 
        $stmt->execute();
    }
 
    /**
     * 检查用户最近$min分钟密码错误次数
     * $uid 用户ID
     * $min  锁定时间
     * $wTIme 错误次数
     * @return 错误次数超过返回false,其他返回错误次数,提示用户
     */
    protected function checkPassWrongTime($uid, $min=30, $wTime=3)
    {
 
        if ( empty($uid) ) {
 
            throw new \Exception("第一个参数不能为空");
 
        }
 
        $time = time();
        $prevTime = time() - $min*60;
 
        //用户所在登录ip
        $ip = ip2long( $_SERVER[&#39;REMOTE_ADDR&#39;] );
 
 
        //pass_wrong_time_status代表用户输出了密码
        $sql = "select * from user_login_info where uid={$uid} and pass_wrong_time_status=2 and UNIX_TIMESTAMP(logintime) between $prevTime and $time and ipaddr=$ip";
 
        $stmt = $this->pdo->prepare($sql);
 
        $stmt->execute();
 
        $data = $stmt->fetchAll(\PDO::FETCH_ASSOC);
 
 
        //统计错误次数
        $wrongTime = count($data);
 
        //判断错误次数是否超过限制次数
        if ( $wrongTime > $wTime ) {
            return false;
        }
 
        return $wrongTime;
 
    }
 
    public function __call($methodName, $params)
    {
 
        echo &#39;访问的页面不存在&#39;,&#39;<a href="./login.php">返回登录页</a>&#39;;
    }
}
 
$a = @$_GET[&#39;a&#39;]?$_GET[&#39;a&#39;]:&#39;loginPage&#39;;
 
 
$login = new Login();
 
$login->$a();

以上がPHPログイン失敗時の対処法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。