制作中のサイトや、購入者だけに見せたい特典ページなど、
がっつり会員制ログインを作るほどではないけど、URL直打ちで誰でも見えてしまうのは困る…
という場面、けっこうありますよね。
そういうときに便利なのが、PHPのセッションだけで作る“簡易ログイン”です。
データベースもユーザー登録機能も用意せず、決め打ちのIDとパスワードを知っている人だけがページを見られるようにする、超シンプルな仕組みです。
この記事では、PHPセッションを使った簡易ログインの作り方と、ログイン画面/ログイン後画面のサンプルデザインまでまとめて紹介します。
先に大事なポイントを書いておくと、このログインはあくまで「閲覧制限」「制作中サイトの仮ロック」「特典ページの入り口」用であり、会員制サイト・個人情報を扱うサービスなどの本番認証には絶対に使わないでください。
「簡易ログイン」のデモはこちら
簡易ログイン画面のサンプルはこちら
https://sample.web-create-kokusyo.com/sample17/login.php

上記のURLを開くとログインフォームがあります。
入力欄に書いてますが、「id」 と 「password」がそのままIDとパスワードになります。
間違った値を入力した際の入力チェックも実装しています。
今回作る「簡易ログイン」の想定ケース
今回紹介するログインフォームは、IDとパスワードが固定の簡易的なログインフォームです。
そのため、次のような用途を想定しています。
- 制作中サイトを一時的に隠しておきたい(クライアントにだけ見せたい)
- キャンペーン応募者・メルマガ登録者だけが見られる特典ページ
- noteや教材などの「購入者限定おまけページ」への入口
- 社内メンバーだけが見られるお知らせページ・マニュアル
逆に、以下のような用途には向いていません。
- ユーザー登録フォームがある本格的な会員制サイト
- メールアドレスや住所などの個人情報を扱うサービス
- 決済情報・機密情報など、流出すると大きな問題になるデータがあるページ
その場合は、フレームワークや認証ライブラリを使ったちゃんとしたログイン機能を使うようにしましょう。
全体の構成イメージ
ファイル構成はシンプルにこんな感じです。
project/
├─ login.php … ログイン処理(PHP)
├─ login-page.html … ログイン画面テンプレート(HTML)
├─ index.php … ログイン後のトップページ(保護対象)
└─ other-page.php … その他の保護したいページ
- login.php:ID・パスワードのチェックとセッションのセット、ログイン画面の表示
- login-page.html:ログインフォームのデザイン
- index.php / other-page.php:各ページの先頭でセッションチェックをして、未ログインなら login.php へ飛ばす
ログイン処理(login.php)のコード
まずはログイン処理のPHPファイルです。
今回の簡易ログインシステムの肝となるファイルです。
コードの重要な部分のみ解説しています。
全ソースは最後に掲載しています。
<?php
// ログインID・パスワード(ベタ書きなので本番認証には使わない)
define("LOGIN_ID", "id");
define("LOGIN_PASSWORD", "password");
// ログイン後に飛ばしたいURL(サイトのトップなど)
define("LOGIN_AFFTER_URL", "./");
session_start();
// 一旦初期化(ログイン画面を開いたらログアウト扱いにしたい場合)
$_SESSION["user_name"] = null;
$error_message = "";
$error_message2 = "";
// ログインボタンが押されたとき
if (isset($_POST["login"])) {
// IDとパスワードのチェック
if ($_POST["id"] === LOGIN_ID && $_POST["password"] === LOGIN_PASSWORD) {
// ★ログイン成功時はセッションIDを再発行しておく
session_regenerate_id(true);
// ログイン済みフラグとしてIDを保存
$_SESSION["user_name"] = LOGIN_ID;
// ログイン後URLへリダイレクト
$login_success_url = LOGIN_AFFTER_URL;
header("Location: {$login_success_url}");
exit;
}
// 認証に失敗した場合
$error_message = "ログインできません。";
$error_message2 = "ID、パスワードをご確認ください。";
define("LOGIN_ERROR", true);
include(dirname(__FILE__) . "/login-page.html");
} else {
// 初回アクセス(フォーム表示)
include(dirname(__FILE__) . "/login-page.html");
}
exit;
?>ポイントを簡単に整理しておきます。
- LOGIN_ID / LOGIN_PASSWORD は決め打ちの1組だけ(超シンプル)
- ログイン成功時に session_regenerate_id(true); を呼んで、ログイン前のセッションIDを捨てるようにしています
- 認証失敗時はフラグ LOGIN_ERRORとメッセージをセットして、login-page.html 側でエラー表示できるようにしています
ログイン画面(login-page.html)
ログイン画面(login-page.html)のフォーム部分のコードです。
<?php if (defined("LOGIN_ERROR") && LOGIN_ERROR): ?>
<div class="login__error">
<strong><?php echo htmlspecialchars($error_message, ENT_QUOTES, "UTF-8"); ?></strong><br>
<?php echo htmlspecialchars($error_message2, ENT_QUOTES, "UTF-8"); ?>
</div>
<?php endif; ?>
<form method="post" action="login.php">
<div class="login__field">
<label class="login__label-text" for="login-id">ID</label>
<input class="login__input" type="text" name="id" id="login-id" autocomplete="off">
<p class="login__hint">サンプル:<code>id</code></p>
</div>
<div class="login__field">
<label class="login__label-text" for="login-password">パスワード</label>
<input class="login__input" type="password" name="password" id="login-password" autocomplete="off">
<p class="login__hint">サンプル:<code>password</code></p>
</div>
<div class="login__actions">
<button class="login__button" type="submit" name="login" value="1">
ログイン
</button>
</div>
</form>エラーメッセージ部分は、login.php でセットした$error_message / $error_message2 / LOGIN_ERROR を利用しています。
各ページでのログインチェック
ログイン後に見せたいページ(index.php や other-page.php)の先頭には、次のようなセッションチェックを入れます。
<?php
// ログインチェック
session_start();
if (!isset($_SESSION["user_name"])) {
header("Location: login.php");
exit;
}
?>これが入っていれば、URL直打ちで index.php を開こうとしても、未ログインなら login.php に飛ばされるようになります。
なぜ session_regenerate_id( ) を入れておくのか
今回のような簡易ログインでも、session_regenerate_id(true); を1行入れておくと、
「ログイン前に使っていたセッションIDを捨てて、新しいIDに差し替える」 ことができます。
これによって、セッションIDの固定(攻撃者にセッションIDを決められてしまうパターン)のリスクを下げることができます。
本格的な会員制サイトでは必須に近い対応ですが、簡易ログインでも入れておいて損はないので、
ログイン成功時にセットで書いておくクセを付けておくと良いと思います。
この簡易ログインを使うときの注意点
- パスワードはPHPファイル内にベタ書きなので、GitHubなどに公開しないように注意
- ログインページ・保護ページは、必ずhttpsで配信する(テスト環境含む)
- 個人情報・決済情報・機密情報を扱うページにはこの仕組みを使わず、フレームワークや認証ライブラリを利用する
あくまで、「制作中サイトの簡易的な閲覧制限」「特典ページや限定コンテンツの入り口」「社内限定ページ」など、ライトな用途向けの仕組みとして使ってもらえればと思います。
まとめ
この記事では、PHPセッションだけで作る簡易ログインの仕組みと、
ログイン画面・ログイン後画面のサンプルデザインを紹介しました。
- ログイン処理は
login.phpにまとめる - 各ページの先頭でセッションチェックを行い、未ログインなら
login.phpへ - ログイン成功時には
session_regenerate_id(true);を入れておく - 用途はあくまで「簡易的な閲覧制限」まで。本番認証には別の仕組みを使う
実務では、「そこまで厳重なログインは要らないけど、誰でも見えてしまうのは困る」という場面が意外と多いので、こういった簡易ログインのパターンを1つ持っておくと、ちょっとした案件で役に立つはずです。
全コード
login.php
<?php
// ログインID・パスワード(ベタ書きなので本番認証には使わない)
define("LOGIN_ID", "id");
define("LOGIN_PASSWORD", "password");
// ログイン後に飛ばしたいURL(サイトのトップなど)
define("LOGIN_AFFTER_URL", "./");
session_start();
// 一旦初期化(ログイン画面を開いたらログアウト扱いにしたい場合)
$_SESSION["user_name"] = null;
$error_message = "";
$error_message2 = "";
// ログインボタンが押されたとき
if (isset($_POST["login"])) {
// IDとパスワードのチェック
if ($_POST["id"] === LOGIN_ID && $_POST["password"] === LOGIN_PASSWORD) {
// ★ログイン成功時はセッションIDを再発行しておく
session_regenerate_id(true);
// ログイン済みフラグとしてIDを保存
$_SESSION["user_name"] = LOGIN_ID;
// ログイン後URLへリダイレクト
$login_success_url = LOGIN_AFFTER_URL;
header("Location: {$login_success_url}");
exit;
}
// 認証に失敗した場合
$error_message = "ログインできません。";
$error_message2 = "ID、パスワードをご確認ください。";
define("LOGIN_ERROR", true);
include(dirname(__FILE__) . "/login-page.html");
} else {
// 初回アクセス(フォーム表示)
include(dirname(__FILE__) . "/login-page.html");
}
exit;
?>login-page.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>ログイン|簡易ログインサンプル</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
:root {
--bg: #0f172a;
--card: #ffffff;
--accent: #2563eb;
--accent-soft: rgba(37, 99, 235, 0.15);
--border: #e5e7eb;
--text-main: #111827;
--text-sub: #6b7280;
--danger: #dc2626;
}
* {
box-sizing: border-box;
}
body {
margin: 0;
min-height: 100vh;
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
background: radial-gradient(circle at top, #1d4ed8 0, #0f172a 50%, #020617 100%);
display: flex;
align-items: center;
justify-content: center;
padding: 24px;
}
.login {
width: 100%;
max-width: 420px;
background: var(--card);
border-radius: 20px;
padding: 28px 24px 24px;
box-shadow: 0 24px 60px rgba(15, 23, 42, 0.4);
}
.login__label {
display: inline-flex;
align-items: center;
gap: 6px;
font-size: 11px;
padding: 4px 8px;
border-radius: 9999px;
background: var(--accent-soft);
color: var(--accent);
margin-bottom: 10px;
}
.login__label-dot {
width: 6px;
height: 6px;
border-radius: 9999px;
background: var(--accent);
}
.login__title {
font-size: 20px;
font-weight: 600;
margin-bottom: 4px;
color: var(--text-main);
}
.login__subtitle {
font-size: 12px;
color: var(--text-sub);
margin-bottom: 20px;
line-height: 1.6;
}
.login__error {
border-radius: 10px;
padding: 10px 12px;
background: #fef2f2;
color: var(--danger);
font-size: 12px;
margin-bottom: 16px;
border: 1px solid #fecaca;
}
.login__field {
margin-bottom: 16px;
}
.login__label-text {
display: block;
font-size: 12px;
font-weight: 500;
margin-bottom: 4px;
color: var(--text-main);
}
.login__input {
width: 100%;
padding: 9px 10px;
border-radius: 10px;
border: 1px solid var(--border);
font-size: 14px;
outline: none;
transition: border-color 0.15s, box-shadow 0.15s;
}
.login__input:focus {
border-color: var(--accent);
box-shadow: 0 0 0 1px rgba(37, 99, 235, 0.3);
}
.login__hint {
font-size: 11px;
color: var(--text-sub);
margin-top: 4px;
}
.login__actions {
margin-top: 8px;
display: flex;
justify-content: flex-end;
}
.login__button {
border: none;
border-radius: 9999px;
padding: 9px 18px;
font-size: 13px;
font-weight: 600;
background: var(--accent);
color: #fff;
cursor: pointer;
box-shadow: 0 10px 20px rgba(37, 99, 235, 0.35);
transition: transform 0.1s ease, box-shadow 0.1s ease, background 0.1s;
}
.login__button:hover {
background: #1d4ed8;
box-shadow: 0 14px 30px rgba(37, 99, 235, 0.45);
transform: translateY(-1px);
}
.login__button:active {
transform: translateY(0);
box-shadow: 0 8px 18px rgba(37, 99, 235, 0.35);
}
.login__footer {
margin-top: 16px;
font-size: 10px;
color: var(--text-sub);
text-align: right;
}
</style>
</head>
<body>
<div class="login">
<div class="login__label">
<span class="login__label-dot"></span>
<span>Internal only</span>
</div>
<h1 class="login__title">簡易ログイン</h1>
<p class="login__subtitle">
制作中サイトや社内限定ページなど、URLを知っている人だけが見られれば良いページ向けの簡易ログインです。<br>
会員制サイトや個人情報を扱うサービスでは利用しないでください。
</p>
<?php if (defined("LOGIN_ERROR") && LOGIN_ERROR): ?>
<div class="login__error">
<strong><?php echo htmlspecialchars($error_message, ENT_QUOTES, "UTF-8"); ?></strong><br>
<?php echo htmlspecialchars($error_message2, ENT_QUOTES, "UTF-8"); ?>
</div>
<?php endif; ?>
<form method="post" action="login.php">
<div class="login__field">
<label class="login__label-text" for="login-id">ID</label>
<input class="login__input" type="text" name="id" id="login-id" autocomplete="off">
<p class="login__hint">サンプル:<code>id</code></p>
</div>
<div class="login__field">
<label class="login__label-text" for="login-password">パスワード</label>
<input class="login__input" type="password" name="password" id="login-password" autocomplete="off">
<p class="login__hint">サンプル:<code>password</code></p>
</div>
<div class="login__actions">
<button class="login__button" type="submit" name="login" value="1">
ログイン
</button>
</div>
</form>
<div class="login__footer">
※ このログインは簡易的な閲覧制限用です。本番の会員制サイトには利用しないでください。
</div>
</div>
</body>
</html>login-page.html
<?php
// ログインチェック
session_start();
if (!isset($_SESSION["user_name"])) {
header("Location: login.php");
exit;
}
?>
<!DOCTYPE html>
<html lang="ja">
ココはご自由に
</html>
