とある理由でパスワードをハッシュ化せずにログインできる必要が出来たのでやってみました。
出来上がってみると割と公式サイトに書いてあることをちゃんと理解できればやれたかもしれないけど最初はやっぱりこれだけじゃ無理。
やったことはLaravel公式のAuthから必要なクラスを継承することで対応しました。
- Illuminate\Auth\SessionGuardを継承。cycleRememberTokenメソッドをオーバーライド
- Illuminate\Auth\EloquentUserProviderを継承。validateCredentialsメソッドをオーバーライド
- app\Providers\AuthServiceProvider.phpに継承したクラスを登録
- config\auth.phpの設定を変更
一応関係するvendorの中のクラスを確認します。
Illuminate\Foundation\Auth\AuthenticatesUsers
LoginControllerの本体のようなもの。traitで組み込まれている。
ログインするときはこのクラスのloginメソッドが呼び出される。
Illuminate\Auth\SessionGuard
認証の本体。これを継承した。
実は今回の認証には必要なかったけど、テーブルにremember_tokenフィールドを追加できなかったので書き込まないようにオーバーライドして対応した。
Illuminate\Auth\EloquentUserProvider
主にデータのやり取りをするクラス。これも継承した。
validateCredentialsメソッドでハッシュ化されたパスワードのチェックをしているのでこれをプレーンなパスワードのチェックに変える。
Illuminate\Auth\AuthManager
このクラスがSessionGuardをnewしている。直にnew SessionGuardとか書いてある。
AuthenticatesUsersのAuthはこのクラスのこと。
実際に継承、設定したコードは以下のようになります。
Illuminate\Auth\SessionGuardの継承
cycleRememberTokenをオーバーライドしてremember_tokenへの書き込みを行わないようにしている
<?php namespace App\Auth; use Illuminate\Auth\SessionGuard; use Illuminate\Contracts\Session\Session; use Illuminate\Contracts\Auth\UserProvider; use Symfony\Component\HttpFoundation\Request; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; class MySessionGuard extends SessionGuard { protected function cycleRememberToken(AuthenticatableContract $user) { // $user->setRememberToken($token = Str::random(60)); // $this->provider->updateRememberToken($user, $token); } }
Illuminate\Auth\EloquentUserProviderを継承。validateCredentialsメソッドをオーバーライド
validateCredentialsをオーバーライドしてハッシュによる認証をやめてプレーンなパスワードのチェックに変える。
ハッシュのチェックにできたらこれは消そう!
<?php namespace App\Auth; use Illuminate\Auth\EloquentUserProvider; use Illuminate\Contracts\Hashing\Hasher as HasherContract; use Illuminate\Contracts\Auth\Authenticatable as UserContract; class MyEloquentUserProvider extends EloquentUserProvider { public function validateCredentials(UserContract $user, array $credentials) { $plain = $credentials['password']; // プレーンなパスワードによる認証 return $plain==$user->getAuthPassword(); // ハッシュ値による認証 // return $this->hasher->check($plain, $user->getAuthPassword()); } }
app\Providers\AuthServiceProvider.phpに継承したクラスを登録
継承して作ったMySessionGuard,MyEloquentUserProviderを認証で使えるようにする。
これは公式サイトにも書いてあった。
<?php namespace App\Providers; use Illuminate\Support\Facades\Gate; use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; use App\Auth\MySessionGuard; use App\Auth\MyEloquentUserProvider; use Auth; class AuthServiceProvider extends ServiceProvider { protected $policies = [ 'App\Model' => 'App\Policies\ModelPolicy', ]; public function boot() { $this->registerPolicies(); // $this->app['auth']->extend('my_session', function($app, $name, array $config) { $provider = Auth::createUserProvider($config['provider']); return new MySessionGuard($name, $provider, $app['session.store']); }); Auth::provider('my_eloquent', function($app, array $config) { return new MyEloquentUserProvider($app['hash'], $config['model']); }); } }
config\auth.phpの設定を変更
AuthServiceProviderで設定したmy_sessionとmy_eloquentを設定する。
<?php return [ 'defaults' => [ 'guard' => 'web', 'passwords' => 'users', ], 'guards' => [ 'web' => [ 'driver' => 'my_session', 'provider' => 'users', ], 'api' => [ 'driver' => 'token', 'provider' => 'users', ], ], 'providers' => [ 'users' => [ 'driver' => 'my_eloquent', 'model' => App\Eloquents\User::class, ], ], 'passwords' => [ 'users' => [ 'provider' => 'users', 'table' => 'password_resets', 'expire' => 60, ], ], ];
かなりお世話になったサイト
Laravel5.2でトークン認証をカスタマイズしてみる
この方はトークン認証についてやっていますが流れは同じ。大いに助かりました。
Laravelのmiddleware authを理解したい
認証の流れが良くわかります。ファサード使っている部分はけっこう迷子になって困ったので非常に助かりました。