Laravel本体の認証機能とは別にDB情報を使わないbasic認証を実装するサンプル

## 1. はじめに

現在Laravelで個人的にサービス開発を行っていて、Laravelのログイン機能とは別basic認証を作成する際の簡単なTipsを今回はご紹介します。
Laravelは始めからE-mailアドレスとパスワードを用いた認証機能の雛形が用意されてたり、basic認証の機構も用意されているのですが、「E-mailアドレスとパスワードを用いた認証にプラスしてbasic認証をつけたい」等の要件がある場合のケースの場合はどうするのだろう？と疑問に思って実装してみました。

Basic認証に関しては、公式ドキュメントのコード例として下記のようなコードが掲載されています。

```php:app/Http/routes.php
Route::get('admin', ['middleware' => 'auth.basic', function() {
    // 認証済みユーザーのみが入れる…
}]);
```

上記のようにLaravelのmiddlewareという機構を利用してお手軽に実装できるのですが、Laravelのbasic認証はデフォルトではDBに登録されている情報を利用する感じになります。この認証機構をカスタマイズすることも可能だとは思いますが、今回はLaravelが提供している認証機能は使いながらも全く別物のBasic認証機能をお手軽に作成することを目的としています。

+ [How to create http basic Authentication in Laravel 5?](http://stackoverflow.com/questions/35227394/how-to-create-http-basic-authentication-in-laravel-5/35232808)

JFYI: Laravelのミドルウェアに関する参考記事

+ [Laravel5のミドルウェアの使い方](http://qiita.com/sogawa@github/items/c6ac3e9f46447aa32668)
+ [Laravel 5.1 HTTPミドルウェア](https://readouble.com/laravel/5.1/ja/middleware.html)


今回はライブラリを活用して、

+ 会員登録が必要な画面や機能 → LaravelのE-mailアドレスとパスワードを用いた認証機能
+ 特定のルーティングに応じてBasic認証をかけたいページが存在する → Laravelの認証機能とは切り離したBasic認証

というものを想定したサンプルコードと解説にしてみました。

JFYI: 認証機能の方法や実装に関しては下記のリンクが参考になります。

+ [Laravel 5.1の認証に関するドキュメント](https://readouble.com/laravel/5.1/ja/authentication.html)
+ [ララ帳：初めてのLaravel 5.1:(28) 認証](https://laravel10.wordpress.com/2015/03/24/%e5%88%9d%e3%82%81%e3%81%a6%e3%81%aelaravel-5-28-%e8%aa%8d%e8%a8%bc/)
+ [ララ帳：初めてのLaravel 5.1:(29) パスワード再設定](https://laravel10.wordpress.com/2015/03/25/%e5%88%9d%e3%82%81%e3%81%a6%e3%81%aelaravel-5-29-%e3%83%91%e3%82%b9%e3%83%af%e3%83%bc%e3%83%89%e5%86%8d%e8%a8%ad%e5%ae%9a/)

## 2. 使用するライブラリと設定方法

使用するライブラリは__「l5-very-basic-auth 」__というライブラリです。

+ [olssonm/l5-very-basic-auth](https://packagist.org/packages/olssonm/l5-very-basic-auth)

ドキュメントは英語なのですが、実装手順や利用方法も結構詳細に記述されていますが、今回は以前に作成した「[Laravelの環境設定＆開発体験自作Laravel5.1ミニマムチュートリアルまとめ](http://qiita.com/fumiyasac@github/items/78a335880f7abb1de8bf)」で紹介したソースへ追記してみようと思います。

私の環境で試したのでOSやMAMPのバージョンは下記の通りになっています。

+ OS：10.10.6 El Capitan
+ MAMP：Ver.3.4（最新版のVer3.5でも問題はないはず）
+ Laravel：5.1 ※LTSバージョン

また今回の追加した差分とリポジトリが下記になりますので、是非ともご参考にして頂ければ幸いです。

+ [Githubのリポジトリはこちら](http://qiita.com/fumiyasac@github/items/78a335880f7abb1de8bf)
+ [今回の追加分：特定アクションにbasic認証をつける](https://github.com/fumiyasac/laravel-minimum-tutorial/commit/fbda815499857b0b64ed46b02c24b3553f3c12f3)

###### ☆手順1: Composerでライブラリのインストールと設定ファイルの準備

まずはcomposer.jsonに下記のように追加をしてあげます。

```json:composer.json
"require": {
    "php": ">=5.5.9",
    "laravel/framework": "5.1.*",
    "laravelcollective/html": "~5.0",
    "laravel-ja/comja5": "^1.0",
    "codesleeve/laravel-stapler": "1.0.*",
    "aws/aws-sdk-php": "2.4.*",
    "olssonm/l5-very-basic-auth": "^1.2" //この部分を追記する
},
```

記述が終わった際は下記のコマンドで「l5-very-basic-auth」を作成しているLaravelアプリケーションにインストールして下さい。またl5-very-basic-authの設定ファイルをconfig配下に書き出す為のコマンドも実行して下さい。

```
$ composer update
$ php artisan vendor:publish --provider="Olssonm\VeryBasicAuth\VeryBasicAuthServiceProvider"
```

また、「l5-very-basic-auth」を使うという宣言も忘れないように追加しておいて下さい。

```php:config/app.php
return [

    //——(省略)—-

    //サービス・プロバイダーの設定
    'providers' => [

        //——(省略)—-
        Olssonm\VeryBasicAuth\VeryBasicAuthServiceProvider::class,
    ],

    //——(省略)—-

];
```

ここまで出来れば、まずは準備は完了です。

###### ☆手順2: 設定ファイルでBasic認証用のID/PASSWORDを設定

次に先ほどのコマンドで出力した設定ファイルにBasic認証用のID/PASSWORDを設定していきます。一応デフォルトでID/PASSWORDは出力されてはいますが、お好みで変更することも可能です。

__（注意）__
実際にWebサービスやネイティブアプリのAPIとして活用する際には、.gitignoreファイルに下記のソースを追記する等をするようにして下さい。また、このファイルのパーミッションも適宜変更して下さい。


```php:config/very_basic_auth.php
<?php

    /**
     * Configuration for the "HTTP Very Basic Auth"-middleware
     */
    return [
        // Username
        'user'              => '任意のユーザーID',

        // Password
        'password'          => '任意のユーザーPASSWORD',

        // Environments where the middleware is active
        'envs'              => [
            'local',
            'dev',
            'development',
            'staging',
            'production',
            'testing'
        ],

        // Message to display if the user "opts out"/clicks "cancel"
        'error_message'     => 'You have to supply your credentials to access this resource.'
    ];

```

このファイルで適用する環境やエラーメッセージの設定なども可能です。
「l5-very-basic-auth」で提供されるbasic認証はLaravel本体の認証とは別ものになります。

## 3. ルーティング部分の記述とアクセス権限のテスト

そして次にルーティングの中に「l5-very-basic-auth」を適用していきます。記述の方法に関してはLaravelで認証が必要なルーティングの設定と同じような記述をします。basic認証で利用するミドルウェアを「l5-very-basic-auth」に変更する形になります。

###### ☆手順1: 実際のルーティングの記述

今回は以前のサンプルに追加・変更・削除を行う際には、認証を通過しないとできないように設定を行います。

```php:app/Http/routes.php
//全トピック表示画面
Route::get('/', 'TopicsController@index');

//任意idのトピック表示
Route::get('/topics/show/{id}', 'TopicsController@show');

//追記：新しく追加・変更・削除のURLに行く際は認証を通過しないといけないようにする
Route::group(['middleware' => 'auth.very_basic', 'prefix' => ''], function() {

    //トピックの新規追加画面
    Route::get('/topics/add', 'TopicsController@add');
    Route::post('/topics/create', 'TopicsController@create');

    //任意idのトピック編集
    Route::get('/topics/edit/{id}', 'TopicsController@edit');
    Route::post('/topics/update/{id}', 'TopicsController@update');

    //任意idのトピック削除
    Route::post('/topics/delete', 'TopicsController@delete');
});
```

追加・変更・削除のいずれかのボタンを押すと、下記の画面のようにbasic認証が通ればOKです。

![basic_auth_success.png](https://qiita-image-store.s3.amazonaws.com/0/17400/0dded8bc-9aaa-d2ab-1b38-d17761283b5b.png)

また、`'prefix' => 'admin'`と設定すれば、追加・変更・削除のページは `(ドメイン名)/admin/edit/1`のようにすることも可能になります。

このようにLaravelで標準搭載の認証機能とは別立てで結構簡単にLaravelのDBを使用しないBasic認証を付与する機構をつくることができます。

###### ☆手順2: ルーティングのテスト

おまけとして簡単にきちんとbasic認証ができているかのユニットテストのコード例を書いておきます。
testsディレクトリの中に任意のphpファイルを作って下記のように記述をします。

```php:tests/ApplicationRoutingTest.php
<?php

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;

class ApplicationRoutingTest extends TestCase
{
    /**
     * ルーティングのテスト（basic認証が設定されているかのテスト）
     *
     * @return void
     */

    /* Basic認証があって誤ったID/PASSWORDだと401になるテスト */
    public function testIncorrectBasicAuthLogin() {

        //誤ったID/PASSWORDを記述
        $basic_auth_config_incorrect = ['user' => 'admin', 'password' => 'admin12'];

        //call( $method, $uri, $parameters = [], $cookies = [], $files = [], $server = [], $content = null)
        $this->call('GET', '/topics/add', [], [], [], ['PHP_AUTH_USER' => $basic_auth_config_incorrect['user'], 'PHP_AUTH_PW' => $basic_auth_config_incorrect['password']]);
        $this->assertResponseStatus(401);

        $this->call('GET', '/topics/edit/1', [], [], [], ['PHP_AUTH_USER' => $basic_auth_config_incorrect['user'], 'PHP_AUTH_PW' => $basic_auth_config_incorrect['password']]);
        $this->assertResponseStatus(401);

        //　このテストケースはコメントアウト
        //$this->call('POST', 'topics/delete', [], [], [], ['PHP_AUTH_USER' => $basic_auth_config_incorrect['user'], 'PHP_AUTH_PW' => $basic_auth_config_incorrect['password']]);
        //$this->assertResponseStatus(500);
    }

    /* Basic認証がないルーティングのときのテスト */
    public function testCorrectWithoutBasicAuthLogin() {

        //call( $method, $uri, $parameters = [], $cookies = [], $files = [], $server = [], $content = null)
        $this->call('GET', '/', [], [], [], []);
        $this->assertResponseStatus(200);

        $this->call('GET', '/topics/show/1', [], [], [], []);
        $this->assertResponseStatus(200);
    }

}
```

こちらはごく平凡なステータスコードを返却するだけのテストケースになりますが、参考になれば幸いです。
また、Laravelには初めからphpunitがあるので、配置したディレクトリで下記のコマンドを実行すればユニットテストが走ります。

```
$ php vendor/bin/phpunit tests/ApplicationRoutingTest.php
```

今回はモデルやコントローラー等のテストは書いていませんが、今回はライブラリの機能がしっかりと担保されていることの確認なのでいったんこれでよしとします。

## 4. あとがき

Laravelには多くの便利かつ強力な機能と多彩なライブラリが魅力なPHPフレームワークですが、フレームワークの範囲からずれてしまう機能を作成する場合には自前で実装するかライブラリを探すかの選択肢がありますが、今回のように認証の部分に関してはなかなか自前ではやりにくい部分ではあると思います。

今回はかなりシンプルなライブラリの紹介にはなりましたが、今回の内容やソースコードに関して疑問点やご意見などがありましたらご遠慮なく宜しくお願い致しますm(_ _)m