Laravel4、認証の新機能

タグ: Laravel4  

Laravel4の認証機能を見て行きましょう。この記事は前記事の続きです。

*参照:UserクラスでCRUD

なお、この記事を書いているのはベータ4リリース後です。正式版では変更になる点もあるでしょう。ご注意ください。

ログイン

前回と同様、ルートの定義はroutes.phpで行います。

いつもユーザー名とパスワードではなんなんで、今回はユーザー名かメルアド、どちらでも認証できるように作成しました。

Route::get( '/login',
    function()
    {
        $warning = Session::get( 'warning', '' );
        return View::make( 'user.login' )
                ->with( 'warning', $warning );
    } );

Route::post( '/login',
    array ( 'before' => 'csrf', function()
    {
        $inputs = Input::only(
                array ( 'username', 'email', 'password' )
        );

        if ( $inputs['username'] == "" and $inputs['email'] == "" )
        {
            return Redirect::back()
                    ->withInput()
                    ->with( 'warning', 
                'ユーザー名、もしくはメールアドレスのどちらかを指定してください。' );
        }

        $rules = array (
            'password' => array ( 'required' ),
        );

        $val = Validator::make( $inputs, $rules );


        if ( $val->fails() )
        {
            return Redirect::back()
                    ->withErrors( $val )
                    ->withInput()
                    ->with( 'warning', 'バリデーションエラーです。' );
        }

        if ( !Auth::attempt( 
             array_only( $inputs, array ( 'username', 'password' ) ) ) )
        {
            if ( !Auth::attempt( 
                 array_only( $inputs, array ( 'email', 'password' ) ) ) )
            {
                return Redirect::back()
                        ->withInput()
                        ->with( 'warning', 
   'ユーザー名/メールアドレスとパスワードの組み合わせが異なっているようです。' );
            }
        }
        return Redirect::to( '/' );
    } ) );

ビューはapp/views/login.phpです。

@if (isset($warning))
    {{ $warning }}
@endif
{{ Form::open() }}
<p>
{{ Form::label('username', 'ユーザー名') }}
{{ Form::text('username', Input::old('username', '')) }}
{{ $errors->first('username') }}
</p>
<p>
{{ Form::label('email', 'メールアドレス') }}
{{ Form::text('email', Input::old('email', '')) }}
{{ $errors->first('email') }}
</p>
<p>
{{ Form::label('password', 'パスワード') }}
{{ Form::password('password') }}
{{ $errors->first('password') }}
</p>
{{ Form::submit('ログイン') }}
{{ Form::token() }}
{{ Form::close() }}

さて、変更になったのは、ユーザー認証をAuth::attempt()で行うのですが、どのテーブル上のカラムであっても認証に利用できるようになりました。

Laravel3でも可能だった?その通りですが、設定ファイルで指定する必要がありました。Laravel4では、設定ファイルで指定する必要は無くなりました。attemptで渡した配列内の項目を使用して認証します。

この配列は1.passwordを含み、2.それ以外の項目で一意にレコードが決まる必要があります。(そうでないと、まともに認証できませんからね。)

簡単に言えばパスワードの他にユーザー名を使用するなら、ユーザー名だけでSELECTして、レコードが1件のみ引けるように、重複を許さないようにします。メールアドレスを使用する場合も同様、重複を許しません。

もし、例えばメールアドレスとユーザー名の重複を許し、その代わりに2つの組み合わせで一意になるようにユーザー登録を行えば、メールアドレスとユーザー名両方とパスワードの組み合わせで、認証するシステムも作成できます。(できますが、ユーザーは嫌がるでしょう。入力が面倒ですからね。)

上記のルート定義では、最初にユーザー名とパスワードで認証を行い、失敗したらメールアドレスとパスワードで認証を行なっています。こんなことが簡単にできるようになりました。

今回のusersにはランクカラムを入れてあります。100が管理者、1が一般ユーザーです。これを利用してスーパーユーザーのみログインさせる専門のページを作成できます。

ビューはsuperlogin.blade.phpです。

@if (isset($warning))
    {{ $warning }}
@endif
{{ Form::open() }}
<p>
{{ Form::label('username', 'ユーザー名') }}
{{ Form::text('username', Input::old('username', '')) }}
{{ $errors->first('username') }}
</p>
<p>
{{ Form::label('password', 'パスワード') }}
{{ Form::password('password') }}
{{ $errors->first('password') }}
</p>
{{ Form::submit('管理者ログイン') }}
{{ Form::token() }}
{{ Form::close() }}

代わり映えしません。ルートは次のようになります。

Route::get( '/superlogin',
    function()
    {
        $warning = Session::get( 'warning', '' );
        return View::make( 'user.superlogin' )
                ->with( 'warning', $warning );
    } );

Route::post( '/superlogin',
    array ( 'before' => 'csrf', function()
    {
        $inputs = Input::only(
                array ( 'username', 'password' )
        );

        $rules = array (
            'password' => array ( 'required' ),
        );

        $val = Validator::make( $inputs, $rules );


        if ( $val->fails() )
        {
            return Redirect::back()
                    ->withErrors( $val )
                    ->withInput()
                    ->with( 'warning', 'バリデーションエラーです。' );
        }

        $inputs['rank'] = 100;
        if ( !Auth::attempt( $inputs ) )
        {
            return Redirect::back()
                    ->withInput()
                    ->with( 'warning',
    'ユーザー名/メールアドレスとパスワードの組み合わせが異なっているようです。' );
        }

        return Redirect::to( '/' );
    } ) );

ネタを開かせば、'rank'=>100の配列アイテムを付け加え、認証を行なっているだけです。ドキュメントでは、ユーザーアカウントの停止を調べたり、アクティブであるかをチェックしたりする例が示されています。いろいろ、応用可能ですね。