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] 簡易ログイン機能を実装してみた

Last updated at Posted at 2020-08-07

はじめに

phpを使用して、簡易的なログイン認証を実装してみました。(技術力低いのでやばいかもしれないが...)

基本的な流れ

  1. idとpasswordを入力する。
  2. 入力したidとpasswordがデータベースに紐づけされて登録されているかをチェック。
  3. 登録されていたらログインし、以外はエラーを表示する。

まぁ簡易的なのでそんなかんじです笑笑

該当ソースコード

1. login.php

ログインするために、ID、パスワードを入力する画面です。

ログイン画面(login.php)
<?php
    require_once("function.php");
    session_start();
    header("Content-type: text/html; charset=utf-8");
?>

<!doctype html>
<html lang="ja">
<head>
    <link rel="stylesheet" type="text/css" href="style1.css">
</head>
<div class="form-wrapper">
    <h1>ログイン</h1>
    <?php
        if (isset($_SESSION["error_status"])) {
            if ($_SESSION["error_status"] == 1) {
                echo "<h2 style='color:red'>IDまたはパスワードが異なります。</h2>";
            }
            if ($_SESSION["error_status"] == 2) {
                echo "<h2 style='color:red'>不正なリクエストです。</h2>";
            }
    
            //エラー情報のリセット
            $_SESSION["error_status"] = 0;
            }
    ?>

    <form action="login_check.php" method="post">
    <div class="form-item">
        <label for="ID"></label>
        <input type="text" name="id" required="required" placeholder="ID">
    </div>
    <div class="form-item">
        <label for="password"></label>
        <input type="password" name="password" required="required" placeholder="パスワード">
    </div>
    <div class="button-panel">
        <input type="submit" class="button" title="ログイン" value="ログイン">
    </div>
    </form>
    
</div>
</html>

2. login_check.php

入力したID、パスワードが事前に登録されているユーザのものなのかを認証します。

コメント欄での指摘通り、//ログイン失敗 以下のif文がwhileループに入っていると意味がないので、ループ外に出しました。

ログイン認証(login_check.php)
<?php
  require_once("function.php");
  session_start();
  header("Content-type: text/html; charset=utf-8");

  //パラメーター取得
  $id = $_POST['id'];
  $password = $_POST['password'];

  //ログイン判定

  //DB接続
  try {
    /*dbname: test
      host: localhost (DBをローカル環境に置いている)
      username: root
      password: '' (未設定)
    */
    $pdo = new PDO('mysql:dbname=test;host=localhost;charset=utf8mb4', 'root', '', 
    [
      PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
      PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    ]
    );

    $stmt = $pdo->query('SELECT id, password, name FROM user');

    $count = 0;

    while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
      $db_id = $row["id"];
      $db_password = $row["password"];
      $db_name = $row["name"];
      $count = $count + 1;

      // パスワードチェック
      // パスワードが一致したら「1」を、不一致なら「0」を返す
      if(password_verify($password, $db_password)) {
        $hantei = 1;
      } else {
        $hantei = 0;
      }

      if ($id == $db_id && $hantei == 1) {
          // ログイン成功
          // セッションに格納することで、ログインユーザ情報をログイン先画面で使用することが可能
    
          //セッション ID の振り直し
          session_regenerate_id(true);
        
          //セッションに ID を格納
          $_SESSION['id'] = $id;

          //セッションに name を格納
          $_SESSION['name'] = $db_name;

          //CSRF のトークン作成
          $_SESSION["token"] = get_csrf_token();
    
          //リダイレクト
          header("HTTP/1.1 301 Moved Permanently");
          header("Location: 〇〇.php"); // ログイン先
      
          exit();
      }
    }

    //ログイン失敗
    if ($count == 0) {
        $_SESSION["error_status"] = 1;
        header("HTTP/1.1 301 Moved Permanently");
        header("Location: login.php"); 
        exit();
    }
  } catch (PDOException $e) {
    exit('データベース接続失敗。'.$e->getMessage());
  }

  //ログイン失敗
  $_SESSION["error_status"] = 1;
  header("HTTP/1.1 301 Moved Permanently");
  header("Location: login.php"); 
    
?>

3. function.php

function.php
<?php
//define("DNS","mysql://user01:0000@localhost/Test?charset=utf8");
define("SERVER", "localhost");
define("STRETCH_COUNT", 1000);

/*
* CSRF トークン作成
*/
function get_csrf_token() {
  $TOKEN_LENGTH = 16;  //16*2=32byte
  $bytes = openssl_random_pseudo_bytes($TOKEN_LENGTH);
  return bin2hex($bytes);
}

/*
* パスワードをソルト+ストレッチング 
*/
function strechedPassword($salt, $password){
    $hash_pass = "";

    for ($i = 0; $i < STRETCH_COUNT; $i++){
        $hash_pass  = hash("sha256", ($hash_pass . $salt . $password));
    }
    
    return $hash_pass;	
}

/*
* ソルトを作成
*/
function get_salt() {
  $TOKEN_LENGTH = 4;//4*2=8byte
  $bytes = openssl_random_pseudo_bytes($TOKEN_LENGTH);
  return bin2hex($bytes);
}

/*
* URL の一時パスワードを作成
*/
function get_url_password() {
  $TOKEN_LENGTH = 16;//16*2=32byte
  $bytes = openssl_random_pseudo_bytes($TOKEN_LENGTH);
  return hash("sha256", $bytes);
}
?>

環境

windows10 64bit
実行環境: xampp (mysql、php、apache等をまとめてインストールでき、インストールも簡単なので)

おわりに

こういう系の記事は初めてなので、見よう見まねで書きました笑笑
抜けている箇所がありましたら、コメント欄で教えていただくとありがたいです。

次回は、ログインアカウントの登録機能について記事を書きたいと思います。
https://qiita.com/N46_myHearter/items/3a34444ef140bc9cb0a8

0
1
2

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?