技術情報

WebAPIで認証【PHP】Slimフレームワークで認証処理の追加法!

WebAPIで認証【PHP】Slimフレームワークで認証処理の追加法!
この記事は、SlimフレームワークでWebAPI化したけど、認証ってどうするの?に答えます。

Slimフレームワークのミドルウェア機能を使って認証方法を実現!使用方法の解説とコーディングサンプルを紹介します。

WebAPIの認証について

今回のサンプルでは認証モデルとして、APIキーを使用したアクセス認証を実装します。
Slimフレームワークのミドルウェア機能を使ってアクセス認証を実装します。

■サンプル仕様

  • ヘッダーパラメータのAPIキーでクライアントを判断する
  • APIキーが渡されない場合には認証エラーを返す

ミドルウェア機能とは?

ミドルウェア機能はHTTPリクエストに対してその入口と出口で動作し、認証からバリデーション、コンテンツ置換など様々な処理を行う事のできるメカニズム

実際のWeb APIロジックの入り口部分で、認証処理を行います。

WebAPI作り方【PHP】Slimフレームワークで既存クラスの使いまわし法! この記事は、Webサイトを作ったけど一部をWebAPI化したいんだよね、どうしたらいいの?に答えます。 高度なURLルーター機能を...

使用方法

Slimフレームワークでのミドルウェアの使用方法はとてもシンプルです。
Appクラスの.addメソッドに引数を渡す事でミドルウェアを登録することが可能です。

※引数にはcallableクラスを実装したクラスもしくは文字列を指定します。

基本構文

下記サンプルのようにクラスを追加した時には、__invokeメソッドが呼び出されます。
※callableクラスを引数に取るメソッドが重要です。

$app = new \Slim\App;

class AuthMiddleware
{
    public function __invoke(Request $request, Response $response,callable $next)
    {
        //認証コード
        $response->getBody()->write("Authorization Check" . PHP_EOL);

        //$nextで実処理に移行します
        $response = $next($request, $response);
        return $response;
    }
}
$app->add(new AuthMiddleware());

ミドルウェア追加時の動き

callableクラスの$nextの呼び出しの前後で、前処理/後処理の動きになります。

  1. AppクラスのrunメソッドでWeb APIを呼び出す
  2. Appクラスにミドルウェアが追加されていた場合、callable実装メソッドを呼び出す
  3. メソッド内でcallableメソッドを呼び出し処理をAPIに戻す
  4. API終了後、callableメソッドに戻る
WebAPIで認証【PHP】Slimフレームワークで認証処理の追加法!-認証フロー図

クロージャー指定方法

独自クラスする必要のない場合には、クロージャー指定で直接function構文に記述する事もできます。

$app->add(function (Request $request, Response $response,callable $next) {
    //認証コード
});

特定APIだけ使用する場合

全てのAPIが同一の認証を行わない場合もあると思います。

その場合には、Web APIのチェーンメソッドにて特定のAPIのみに追加することができます。

下記サンプルではgetInfoの場合には認証処理が実行されます。

// 認証不要API
$app->get('/getCategory', function (Request $request, Response $response) {
    ...
});

// 認証API
$app->get('/getInfo', function (Request $request, Response $response) {
    ...
})->add(new AuthMiddleware);

サンプル実装

前回のWeb APIに認証機能を追加してみます。

追加コード

今回追加する認証クラスのコードです。
API呼び出し時に、HEADERに”H-API-KEY”キーを追加して値にAPIKEYを渡します。

※サンプルでは分かりやすくハードコーディングしていますが、暗号化や外部ファイル化は必須です。

class AuthMiddleware
{
    const HEADER_API_KEY = 'AUTH_API_KEY_20181203'; 

    public function __invoke(Request $request, Response $response, callable $next)
    {
        // 認証を行う
        $header = $request->getHeaderLine('H-API-KEY');
        if (!$header || $header != self::HEADER_API_KEY) {

            // 認証エラー: 401
            $response = $response->withStatus(401, 'Unauthorized');
            return $response;
        }

        $response = $next($request, $response);
        return $response;
    }
}

結果

今回もGoogle Chromeの拡張機能『Advanced REST client』をセットアップして実行します。

サーバ名はご利用のサーバもしくはローカルテスト環境で実行してみて下さい。

認証成功

前回同様のdbModelのプロパティ値がjsonで戻ります。
WebAPIで認証【PHP】Slimフレームワークで認証処理の追加法!-認証成功結果

認証エラー

AuthMiddlewareクラスで出力した401エラーが戻ります。
WebAPIで認証【PHP】Slimフレームワークで認証処理の追加法!-認証エラー結果

全コード

testAPIクラスのコンストラクタで、AppクラスにAuthMiddlewareを追加します。

<?php

require '../../../vendor/autoload.php';
use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;

function h($str)
{
    return htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
}

class AuthMiddleware
{
    const HEADER_API_KEY = 'AUTH_API_KEY_20181203'; 

    public function __invoke(Request $request, Response $response, callable $next)
    {
        // 認証を行う
        $header = $request->getHeaderLine('H-API-KEY');
        if (!$header || $header != self::HEADER_API_KEY) {

            // 認証エラー: 401
            $response = $response->withStatus(401, 'Unauthorized');
            return $response;
        }

        $response = $next($request, $response);
        return $response;
    }
}

class dbModel{
    public $modelNo;
    public $modelName;

    public function __construct($no,$modelName){
        //引数をメンバー変数に格納
        $this->modelNo = $no;
        $this->modelName = $modelName;
    }
}

class dbController{
    public function getModel(){
        return new dbModel("1", "Slim Taro");
    }
}


class testAPI {
  public $slim;
  public $dbController;


  public function __construct(){
      $this->slim = new \Slim\App();
      $this->slim->add(new AuthMiddleware());
      $this->dbController = new dbController();
      $this->setupRouter();
  }

  public function __destruct(){
      $this->dbController = null;
      $this->slim = null;
  }

  private function setupRouter(){
      $this->slim->get('/', array($this, 'getModel'));
  }

  public function getModel(){
      $result = $this->dbController->getModel();
      $rows = array();
      $rows[]=array(
            'modelNo'=>h($result->modelNo),
            'modelName'=>h($result->modelName)
            );
      header("Content-Type: text/javascript; charset=utf-8");
      echo json_encode($rows);
  }

  public function run(){
    $this->slim->run();
  }
}

$testAPI= new testAPI();
$testAPI->run();

参考サイト

【akamist blog】[PHP]Slim FrameworkでAPIキーによるアクセス認証を実装する」

まとめ

Slimマイクロフレームワークは既存の資産をWeb API化する上でとても便利です!

アプリからの呼び出しにも利用でき、資産+αでより提案内容も充実すると思います。

Web API化する上でのAPI-KEY暗号化サンプルなども発信していきたいと思います!