PHP による単純な JWT 認証の例
このページは、PHP で単純な JWT 認証を行う例を記載するページです。
注意
- コードのライセンスは CC0 (クレジット表示不要、改変可、商用可) です。
- フレームワークを使わない場合に使う用途として想定しています。
- このページでは JWT のライブラリとして firebase/php-jwt (6.1.1) を使用しています。
composer require firebase/php-jwt
サンプルの想定動作
サンプルの想定動作は下記のようなイメージです。
- login.php に下記のリクエストをすると認証が通り JWT トークン (
{ "token": "..." }
) が返却される- ヘッダー:
Content-Type: application/json
- ボディ:
{ "username": "test", "password": "test" }
- ヘッダー:
- data.php に下記のリクエストをするとデータ (
{ "username": "test }
) が返却される- ヘッダー:
Content-Type: application/json
- ヘッダー:
Authorization: Bearer 【index.php で取得したトークン】
- ボディ: なし
- ヘッダー:
コード
.htaccess
RewriteEngine On
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
PHP
<?php
/** JWT のアルゴリズム */
define('JWT_ALG', 'HS256');
/** JWT のキー */
define('JWT_KEY', '1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890');
/** JWT の発行者 */
define('JWT_ISSUER', 'http://localhost');
/** JWT の有効期限 (秒) */
define('JWT_EXPIRES', 3600);
<?php
require __DIR__ . '/const.php';
require __DIR__ . '/vendor/autoload.php';
use Firebase\JWT\JWT;
// POST 時
if (strtoupper($_SERVER['REQUEST_METHOD']) == 'POST') {
$inputString = file_get_contents('php://input'); // JSON 文字列取得
$input = @json_decode($inputString, true);
if (is_array($input)) {
$input = array_merge(array('username' => '', 'password' => ''), $input);
$username = $input['username'];
$password = $input['password'];
$ok = ($username == 'test' && $password == 'test'); // username = test, password = test で認証 OK とする (仮)
if ($ok) {
$payload = array(
'iss' => JWT_ISSUER,
'exp' => time() + JWT_EXPIRES,
'username' => $username,
);
$jwt = JWT::encode($payload, JWT_KEY, JWT_ALG);
header('Content-Type: application/json');
echo json_encode(array('token' => $jwt)); // token を返却
return;
}
}
// JSON 取得失敗、認証に失敗した場合は 401
http_response_code(401);
}
<?php
require __DIR__ . '/const.php';
require __DIR__ . '/vendor/autoload.php';
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
// GET 時
if (strtoupper($_SERVER['REQUEST_METHOD']) == 'GET') {
$auth = isset($_SERVER['HTTP_AUTHORIZATION']) ? $_SERVER['HTTP_AUTHORIZATION'] : '';
if (preg_match('#\ABearer\s+(.+)\z#', $auth, $m)) { // Bearer xxxx...
$jwt = $m[1];
try {
$payload = JWT::decode($jwt, new Key(JWT_KEY, JWT_ALG)); // JWT デコード (失敗時は例外)
$username = $payload->username; // エンコード時のデータ取得
header('Content-Type: application/json');
echo json_encode(array('username' => $username)); // username を返却
return;
}
catch (Exception $e) {}
}
// Bearer が取得できない、JWT のでコードに失敗した場合は 401
http_response_code(401);
}
リクエスト例
※ Visual Studio Code の REST Client 拡張で使用できる形式になっています。data.php の Bearer は login のレスポンスにある token を使用します。
# @name login
POST http://localhost/login.php
Content-Type: application/json
{
"username": "test",
"password": "test"
}
###
GET http://localhost/data.php
Content-Type: application/json
Authorization: Bearer {{login.response.body.$.token}}
実行例
{
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9sb2NhbGhvc3QiLCJleHAiOjE1ODk1NTI1ODksInVzZXJuYW1lIjoidGVzdCJ9.N7gVU75BNSjxrSPPjBU-bLaUbUuFlMP3YHHq5-vGr5s"
}
{
"username": "test"
}