0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

PHPで簡単なログイン機能を作る(パスワードのハッシュ化も)

Posted at

##はじめに
自分でPHPを使ってログイン機能を作ったので、一連の流れをまとめました。
間違えていることなどがあれば、教えてくださるとありがたいです。
PHPのバージョンは7.3を使用しています。
password_hash関数とpassword_verify関数を使ってパスワードのハッシュ化とパスワードの認証をやっていきます。

##そもそもハッシュ化とは
ユーザーのパスワードなど、大切な情報をデータベースに格納する時に、元データをハッシュ関数と呼ばれるものを利用して変換することです。

##ハッシュ関数の特徴
以下の2つが大きな特徴です。
● 元データが同じならば変換後は必ず同じ値になる
● 変換後の値から元データの値を復元することが不可能である

##password_hash関数の書き方

 $password = password_hash([ユーザーが入力したpassword], PASSWORD_DEFAULT);

自分はこのように書きました。$passwordこの変数をDBに格納することで、ハッシュ化されたパスワードを保存することが可能です。ちなみに変数名は何でも大丈夫です。

##注意点
デフォルトのアルゴリズムを使ってパスワードをハッシュするので、現時点でのデフォルトは
BCRYPT で、その結果は 60 文字になります。
デフォルトは、今後変わる可能性があることに注意しましょう。結果が
60文字以上になっても対応できるようにしておきましょう (255 あたりが適切です)
と公式のページに書いていました。 詳しくは、公式ページを見てください。password_hash

##DB設定
DBにuserの情報を追加するテーブルを作成します。カラムはシンプルに名前とパスワードのみにしました。

user_name password
- -

##コード例

<?php

   if(isset($_POST['user_name'])){
     $user_name = $_POST['user_name'];
   }

   if(isset($_POST['user_password'])){
     $user_password = password_hash($_POST['user_password'], PASSWORD_DEFAULT);
   }
?>

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>登録画面</title>
</head>
  <body>

      <!-- ユーザーネーム -->
      <form method = "post">
        <p class="name">ユーザーネーム:
          <input type="text" name="user_name"></p>   

        <!-- パスワード -->
        <p class="password">パスワード:
          <input type="password" name="user_password"></p>
          <input type="submit" value="登録する">
      </form>
  
  </body>
</html>

あとはデータベース接続して、それぞれの変数をテーブルに保存することでハッシュ化は完了です。

##テーブルの中身

user_name password
sample 0$8U6sqRKNF5iYMJ.8zSQ8GOsk2efw2ZFWWKRtDSMGIspTaBOOYcn

user_nameはそのままで、passwordのみランダムな文字列に変換されています。
これで、登録は完了です

##ログイン認証の手順
登録された、データを使ってログインの仕組みを作ります。

      <form method = "post">
        <p class="name">ユーザーネーム:
          <input type="text" name="user_name"></p>   

        <p class="password">パスワード:
          <input type="password" name="user_password"></p>
          <input type="submit" value="ログインする">
      </form>

登録と同じように、ユーザーネームと、パスワードを入力できるフォームを用意します。
認証では、password_verify関数を使います。

##password_verify関数の使い方

password_verify('入力されたパスワード', 'DBに保存したhash化したパスワード')

このように引数が二つ必要になります。

##コード例

<?php

   if(isset($_POST['user_name'])){
     $user_name = $_POST['user_name'];
   }

   if(isset($_POST['user_password'])){
     $user_password = password_hash($_POST['user_password'], PASSWORD_DEFAULT);
   }


 try {
      // データベースに接続
          $dbh = new PDO($dsn, $username, $password, array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8mb4'));
          $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
          $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
                      
          $sql = 'SELECT * FROM users WHERE user_name = :user_name';
          $stmt = $dbh->prepare($sql);
          $stmt->execute(array(':user_name' => $user_name));
          $user = $stmt->fetch(PDO::FETCH_ASSOC);
              
      }catch(PDOException $e){
          echo '接続できませんでした。理由:'.$e->getMessage();
      }

      if($user === false || password_verify($user_password, $user['password']) === false){
          echo 'ログインできませんでした';
        }
        else{
          echo 'ログイン成功';
        }
?>

SELECT文が失敗したり、passwordが間違っていると、ログインできないような条件をif文で書きました。

##最後に
これで、完全に安全というわけではなく、辞書攻撃など弱点もあるので、上記のコードでは、ほとんどバリデーションをしていませんが、なるべく辞書にないような、文字の組み合わせをユーザーに登録させるよう、バリデーションをしていくことが必要だと思います。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?