Laravel5の認証機能 カスタマイズ(テーブルカラムを変更追加する)

LaravelのデフォルトのAuth機能を入れてみてから

とはいえLaravelはデフォルトでそこそこの機能を実装しているのでいたずらにカスタマイズしてももったいないことになるので、ここでは新規登録時にもうちょっと必要な情報も登録できるようにしてみようということをやってみます。ここまでやっている前提となります。デフォルトの認証テーブルになるusersは以下のようになっています。

$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->rememberToken();
$table->timestamps();

これだとちょっと足りないので、後々の用途を考慮して以下のものを追加してみます。ここはマイグレーションのロールバックしてから新規でテーブルを作成してみましょう。

usersテーブルのマイグレーション

$table->increments('id');
$table->string('uniqeid', 64); //(+)
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->rememberToken();
$table->integer('count'); //(+)
$table->integer('active'); //(+)
$table->integer('role'); //(+)
$table->unsignedTinyInteger('delflag'); //(+)
$table->timestamps();

マイグレーションでテーブルの作成をしたら、さっそく新規ユーザーの登録をしてみるとカラム数が全然違うので当然エラーになります。
登録時のカラムをSQL文に通してあげます。

新規登録時のコード

app/Http/Controllers/Auth/RegisterController.php(以下RegisterControllerクラス)が登録時のフロントコントローラになっているのでここらあたりからみていきます。ルーティングでは以下のようになっていて

Method URI Action
GET/HEAD /register App\Http\Controllers\Auth\RegisterController@showRegistrationForm web,guest
POST /register App\Http\Controllers\Auth\RegisterController@register web,guest

RegisterControllerクラスを指していますが該当のメソッドが見当たらないので継承元のvendor/laravel/framework/src/Illuminate/Foundation/Auth/RegistersUsers.php(以下RegistersUsersトレイト)を見ます。
showRegistrationForm()は単に入力フォームを表示しているだけ、register(Request $request)はリクエストデータを受け取ってバリデーションをかけた後に$this->create()でもって(おそらく)保存処理っぽいことをやっているようです。ここらで受け取っているリクエストは、

["_token"]
["name"]
["email"]
["password"]
["password_confirmation"]

でした。って考えるとRegisterControllerクラス-コントローラのcreate(array $data)に追加情報を入れてあげた方が作りとしては無難な気がします。勿論RegistersUserトレイトでいろいろやることもできますが、vender以下は基本さわらないのがルールなのとトレイトは抽象度を高くしておいた方がいいです。
フロントのコントローラでセットした内容は、

vender/laravel/faramework/src/Illuminate/Foundation/Auth/RegistersUser.php
vender/laravel/faramework/src/Illuminate/Events/Registerd.php
app/User.php
vender/laravel/faramework/src/Illuminate/Dtabase/Connectors/Connection.php

ここらあたりを行き来しつつバリデーションとかいろいろやってます。最終的にはUser.phpでいろいろ準備してSQLをConnection.phpあたりに投げて無事登録みたいな流れです。

usersテーブルにカラムを追加する

  • マイグレーション
  • RegistController@createのreturnに追加したカラムの値を追加。
  • User.phpの$fillableプロパティに追加したカラム名を追加。

以上になります。
マイグレーションは終わっていることを前提とします。
ここでは追加カラムに値を入れます。

// app/Http/Controllers/Auth/RegisterController.php
/**
 * Create a new user instance after a valid registration.
 *
 * @param  array  $data
 * @return User
 */
protected function create(array $data)
{
// とりあえず値は入れておく
    $data['uniqeid'] = "xxxxxxxx";
    $data['count'] = 1;
    $data['active'] = 0;
    $data['role'] = 0;
    $data['delflag'] = 0;

    return User::create([
        'uniqeid' => $data['uniqeid'], // 追加
        'name' => $data['name'],
        'email' => $data['email'],
        'password' => bcrypt($data['password']),
        'remember_token' => "",
        'count' => $data['count'],// 追加
        'active' => $data['active'],// 追加
        'role' => $data['role'],// 追加
        'delflag' => $data['delflag'],// 追加
    ]);
}

それからUser.phpの$fillableプロパティに追加したカラム名を追加。
remember_tokenは別のプロパティ($hidden)で設定しているからいらないと思う。

protected $fillable = [
    // 'name', 'email', 'password',
    'uniqeid','name','email','password','count','active','role','delflag', // ←追加したカラム分
];

これで新しく作ったカラムに値が追加されます。

認証に使うテーブル名を変更する。(他のテーブルを使う)

他のテーブルを使いたい場合は、User.phpに

protected $table = 'other_table_name';

で設定してあげるだけでOKです。
認証に利用するモデル自体を変えてしまうという方法もありますが思っていたより面倒なので、User.phpを流用した方が簡単です。

本人認証(メール認証)を加える

冒頭で$table->integer(‘active’)を追加したのは、新規で会員登録した際にはメールアドレスにて本人認証のフローを入れておきたかったからです。登録完了後にメールが飛んで、メールに書かれているURLをクリックしたら本認証(あるいは、URLをクリックしてその先のページでログインしたら本認証)という感じです。
まずはデフォルトでは登録が正常終了したらそのままログインという流れになっているので、完了画面になるように修正します。

  • 登録終了後、完了画面が表示される
  • メールが送信される
  • メール内のURLをクリック(本認証をするUIを作成)
  • Activeフラグを1にして本認証完了
  • ログインのattemptでActiveフラグ追加

みたいなことになります。

完了画面をつくる

vendor/laravel/framework/src/Illuminate/Foundation/Auth/RegistersUsers.phpのregister()でもって登録されたらそのままログインみたいなコードがあります。
デフォルトのままだとevent()にDB登録するデータを入れて、それが成功したらログイン、成功しなかったら$this->redirectPath()に飛ばすということになってます。returnでオリジナルの完了画面のリダイレクトパスを指定すればOK。
※ただこの改造でremember_tokenだけ登録されなかったのですが、ログインてから一回目のログアウト時に登録される仕組みになってました。
Laravelの作りとして、RegistersUsers.phpのregister()を直接改造しないでtraitをオーバーライドする習わしがあります。なので、フロントコントローラであるapp/Http/Controllers/Auth/RegisterController.phpでregister()をオーバーライドします。
細かいこというと、RegistersUsers.phpで使っているものをusesすること。register()内部でさらにregistered()メソッドも使われているので、そのことにも注意しましょう。

// app/Http/Controllers/Auth/RegisterController.php
use RegistersUsers;
....
protected $redirectToStored = '/stored';
....
public function register(Request $request)
{

    $this->validator($request->all())->validate();

    event(new Registered($user = $this->create($request->all())));

    // $this->guard()->login($user);

    // return $this->registered($request, $user)
    //                ?: redirect($this->redirectPath());
    return redirect('/stored'); // ← これ追加
}

/storedのviewはあらかじめつくっておきましょう。
これで新規登録後は/storeが表示されます。
(この画面も直接アクセスすると表示されてしまうので、新規登録のときのみアクセスし表示できるように何らかの処理をしておいた方がよいかもです。token渡すとか。

メールを送信する

メールを送信してURIを踏ませて認証するわけですが、認証に必要なTokenを生成する必要があります。これをどうするかという話なのですが、基本的にはパスワード認証に近しいものが安全といえます。本人確認の方法は最近は様々です。AWSでは電話がかかってくる…ってのもありました。
ここでは便宜的にユーザー名を「Salt and Pepper」的に暗号化して照合するというかたちにします。
メールの送信設定はすでにできていることを前提にすすめます。
メール送信のタイミングは完了画面へのリダイレクトの直前でキューするのが普通なのかなと思います。(キューしないで直接送信する方法もありだとは思います。)
またメールの送信は登録のタイミングでコントローラのどこかで行うのもよいと思いますが、ListnerなるものがLaravelにはあるのでそれを使うのもよいかと思います。

心が折れたので続きはまた今度。

Last update: 2017.07.11 (火)