@半径とことこ60分

人間の認知範囲なんてそんなもんさと、鳥が囀った

プログラマーじゃないけどLaravel4入門(3)blogをつくる

ユーザ認証、ログイン(続き)

認証

ログイン認証のルーティングを route.php に書いてもいいのですが、FogotPassword などの処理もあり、煩雑にならないようコントローラーを使ってみようと思います。

app/controllers/AuthController.php

<?php
class AuthController extends \BaseController {
  public function postLogin(){
    $inputs = Input::only(array('username', 'password'));
    $rules = array (
      'username' => array ( 'required' ),
      'password' => array ( 'required' ),
    );
    $val = Validator::make( $inputs, $rules );
    if ($val->fails())
    {
      return Redirect::back()
        ->withErrors( $val )
        ->withInput();
      }
    if(!Auth::attempt($inputs))
    {
      return Redirect::back()
        ->withErrors(array('warning'=>'Login failed'))
        ->withInput();
    }
    return Redirect::route('dashboard');
  }

  public function getLogout(){
    Auth::logout();
    return Redirect::to('/');
  }
}

routes.php 追加と一部変更。

  • バックエンド dashboard に名前をつけリダイレクト時に簡潔にする

Route::get('admin/dashboard', array('as' => 'dashboard', function()
{
  return 'admin site';
 }));
Route::post('login', 'AuthController@postLogin');
Route::get('logout', 'AuthController@getLogout');

login.blade.php 一部変更。

  • エラー処理部分を変更

@if($errors->has())
  <div class="alert alert-danger">
    <ul>
    @foreach($errors->all() as $warning)
      <li>{{$warning}}</li>
    @endforeach
    </ul>
  </div>
@endif

 で、テストです。

f:id:ausnichts:20140801120402p:plain

(上)バックエンド admin/dashboard にアクセスするとログインフォームへ飛びます。

f:id:ausnichts:20140801120527p:plain

f:id:ausnichts:20140801120625p:plain

(上2つ)バリデーションエラーもうまく拾っています。

f:id:ausnichts:20140801120802p:plain

(上)ログインしますとバックエンドへ飛びます。

ところが、ログアウトしようとしますとエラーが出ます。

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'remember_token' in 'field list' (SQL: update `users` set `updated_at` = 2014-08-01 11:59:57, `remember_token` = WShR3CVA5u0jUld37u3IFnhvt776KKAWMviLr9vctSGWD3TCd7VksGrfYrrj where `id` = 1)

要は「users テーブルに remember_token カラムがないよ」と言っているんですが、処理は後で書けばいいやと、とりあえずログインフォームに「remember me」チェックボックスを作っておいたんですが、エラーはそこらあたりの問題で、多分ログアウトする時にトークンが書き込めないということでしょうね。

remember_token カラムを追加する

remember_token カラム追加のマイグレーションを作成し、

$ php artisan migrate:make AddRemembertokenToUserTable

public function up()
{
  Schema::table('users', function($table)
  {
    $table->string('remember_token')->nullable();
  });
}

実行します。

$ php artisan migrate

これで、ログアウト時のエラーは出なくなりました。

オートログイン、Remember me

実用レベルの認証サンプルが Laravel4.1、認証機能のサンプル にありましたので、参考にさせていただきましょう。

結局、オートログインを有効にするには、ログイン処理をする Login::Atempt() の引数に true を指定すればいいということのようです。

AuthController の該当箇所を一部変更します。

if(!Auth::attempt($inputs, (Input::get( 'remember', '0' ) == '1' )))
{
  return Redirect::back()
    ->withErrors(array('warning'=>'Login failed'))
    ->withInput();
}

ところで、オートログインにチェックしない場合のセッションの有効期限はどれくらいなんでしょう?

app/config/session.php

/*
|--------------------------------------------------------------------------
| Session Lifetime
|--------------------------------------------------------------------------
|
| Here you may specify the number of minutes that you wish the session
| to be allowed to remain idle before it expires. If you want them
| to immediately expire on the browser closing, set that option.
|
*/
'lifetime' => 120,
'expire_on_close' => false,

とあるのがそれでしょうね。デフォルトでは2時間となっており、 expire_on_close は、ブラウザを閉じた時に破棄したい場合は true とすればいいようです。

lifetime を短くしたり、expire_on_close を変更して試してみたところ、確かにこのファイルでコントロールしているようです。じゃ、オートログイン remember me の時間はどこでコントロールしているのでしょうか?

vendor/laravel/framework/src/Illuminate/Cookie/CookieJar.php

/**
* Create a cookie that lasts "forever" (five years).
*
* @param string $name
* @param string $value
* @param string $path
* @param string $domain
* @param bool $secure
* @param bool $httpOnly
* @return \Symfony\Component\HttpFoundation\Cookie
*/
public function forever($name, $value, $path = null, $domain = null, $secure = false, $httpOnly = true)
{
return $this->make($name, $value, 2628000, $path, $domain, $secure, $httpOnly);
}

これですね。2628000÷60÷24÷365=5、5年?ですか!? forever ですね。

CSRF対策

laravel では、フォームを設置すると自動的にトークンが発行されていますので、ログイン時に CSRFフィルタを通すように route.php を変更します。

Route::post('login', array('before' => 'csrf', 'uses' => 'AuthController@postLogin'));

これで、とりあえず自分自身のログイン~認証はできますので、パスワードリマインダーとかユーザ登録などの管理関係は後回しにして、次はブログ記事作成に進もうと思います。

で、この際ということで GitHub なるものも始めました。

ausnichts/laravel4-blog · GitHub