便利なことにLaravel5.2には認証処理がフレームワーク側にある。
先人たちのブログや公式サイトなど眺めてみたものの、ちょっと物足りない…
例えば、ログイン後のリダイレクト先やら、パスワードリセットのメールの内容やら…
セッションが無くなった時にリダイレクト先もなかったかな。
結構疲れた。それはどうでもいい。
ざっと端折りながら書いていく。
クライアント環境:Windows10 XAMPP(PHP7.0.4) Eclipse 4.5.2(Mars) Laravel5.2.33
サーバ環境:CentOS7 MariaDB5.5.47
はじめに
業務システムでは、一般権限のユーザと管理権限のユーザでパスで変えることはよくあると思う。例えば以下の様な感じ。
・一般側
ログイン:http://localhost/login
TOP:http://localhost/top
・管理側
ログイン:http://localhost/admin/login
TOP:http://localhost/admin/top
コマンドプロンプトで、以下を実行すると認証に必要なモジュール一式がインストールされる。注意しないといけないのは、今作ってるところに実行すると上書きされるファイルもあるので要注意!(私は「/resources/views/layouts/app.blade.php」が上書きされて、SVNで元に戻せましたが気をつけましょう。)
>php artisan make:auth
routes
まずは、ルーティング。
Route::auth();
これを追加するだけで、8つのルートが出来上がる。
+--------+----------+------------------------------------+------+-----------------------------------------------------------------+--------------------+
| Domain | Method | URI | Name | Action | Middleware |
+--------+----------+------------------------------------+------+-----------------------------------------------------------------+--------------------+
| | POST | login | | App\Http\Controllers\Auth\AuthController@login | web |
| | GET|HEAD | login | | App\Http\Controllers\Auth\AuthController@showLoginForm | web |
| | GET|HEAD | logout | | App\Http\Controllers\Auth\AuthController@logout | web |
| | POST | password/email | | App\Http\Controllers\Auth\PasswordController@sendResetLinkEmail | web |
| | POST | password/reset | | App\Http\Controllers\Auth\PasswordController@reset | web |
| | GET|HEAD | password/reset/{token?} | | App\Http\Controllers\Auth\PasswordController@showResetForm | web |
| | POST | register | | App\Http\Controllers\Auth\AuthController@register | web |
| | GET|HEAD | register | | App\Http\Controllers\Auth\AuthController@showRegistrationForm | web |
+--------+----------+------------------------------------+------+-----------------------------------------------------------------+--------------------+
※コマンドプロンプトで「php artisan route:list」を実行すると上記が表示される。
「register」ってルートはユーザ登録だと思うがこれは端折る。だって業務システムだと、一般ユーザの登録は管理者が行うから。
それで、ルートを以下の様な感じで修正する。
Route::group(['middleware' => 'guest:user'], function() {
Route::get('/login', 'Auth\AuthController@showLoginForm');
Route::post('/login', 'Auth\AuthController@login');
Route::get('/logout', 'Auth\AuthController@logout');
Route::post('/password/email', 'Auth\PasswordController@sendResetLinkEmail');
Route::post('/password/reset', 'Auth\PasswordController@reset');
Route::get('/password/reset/{token?}', 'Auth\PasswordController@showResetForm');
});
Route::group(['middleware' => 'auth:user'], function() {
Route::get('/home', 'HomeController@top');
});
Route::group(['prefix' => 'admin'], function () {
Route::group(['middleware' => 'guest:admin'], function() {
Route::get('/login', 'Auth\AuthController@showLoginForm');
Route::post('/login', 'Auth\AuthController@login');
Route::get('/logout', 'Auth\AuthController@logout');
Route::post('/password/email', 'Auth\PasswordController@sendResetLinkEmail');
Route::post('/password/reset', 'Auth\PasswordController@reset');
Route::get('/password/reset/{token?}', 'Auth\PasswordController@showResetForm');
});
Route::group(['middleware' => 'auth:admin'], function() {
Route::get('/home', 'HomeController@top');
});
});
そうすると以下のようにルートが出来上がる。
+--------+----------+------------------------------------+------+-----------------------------------------------------------------+--------------------+
| Domain | Method | URI | Name | Action | Middleware |
+--------+----------+------------------------------------+------+-----------------------------------------------------------------+--------------------+
| | GET|HEAD | admin/home | | App\Http\Controllers\HomeController@top | web,auth:admin |
| | GET|HEAD | admin/login | | App\Http\Controllers\Auth\AuthController@showLoginForm | web,guest:admin |
| | POST | admin/login | | App\Http\Controllers\Auth\AuthController@login | web,guest:admin |
| | GET|HEAD | admin/logout | | App\Http\Controllers\Auth\AuthController@logout | web,guest:admin |
| | POST | admin/password/email | | App\Http\Controllers\Auth\PasswordController@sendResetLinkEmail | web,guest:admin |
| | POST | admin/password/reset | | App\Http\Controllers\Auth\PasswordController@reset | web,guest:admin |
| | GET|HEAD | admin/password/reset/{token?} | | App\Http\Controllers\Auth\PasswordController@showResetForm | web,guest:admin |
| | GET|HEAD | home | | App\Http\Controllers\HomeController@top | web,auth:general |
| | POST | login | | App\Http\Controllers\Auth\AuthController@login | web,guest:general |
| | GET|HEAD | login | | App\Http\Controllers\Auth\AuthController@showLoginForm | web,guest:general |
| | GET|HEAD | logout | | App\Http\Controllers\Auth\AuthController@logout | web,guest:general |
| | POST | password/email | | App\Http\Controllers\Auth\PasswordController@sendResetLinkEmail | web,guest:general |
| | POST | password/reset | | App\Http\Controllers\Auth\PasswordController@reset | web,guest:general |
| | GET|HEAD | password/reset/{token?} | | App\Http\Controllers\Auth\PasswordController@showResetForm | web,guest:general |
+--------+----------+------------------------------------+------+-----------------------------------------------------------------+--------------------+
Middlewareにguestってあるのが認証が不要なページ、authってのが認証が必要なページとなる。:(コロン)の後にあるadmin(管理者)とgeneral(一般)については別途。
auth.php
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
],
'general' => [
'driver' => 'session',
'provider' => 'users',
],
'admin' => [
'driver' => 'session',
'provider' => 'users',
],
],
管理者は別テーブルならproviderを変えてあげればOKかと。
Middleware
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class Authenticate
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string|null $guard
* @return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
//if (Auth::guard($guard)->guest()) {
if (Auth::guard(null)->guest()) {
if ($request->ajax() || $request->wantsJson()) {
return response('Unauthorized.', 401);
} else {
return redirect()->guest($guard . '/login');
}
}
return $next($request);
}
}
$guardにはルートで設定したadminとかgeneralが渡ってくるとか書いてあるわけですよ。でも渡ってこないんですよ。何故か。なので、ログイン完了成功してもまたログイン画面に戻ると。。。でAuth::guard(null)に変更してみたら何とかなったのでそんな感じに変更。
さらに、
redirect()->guest($guard . '/login');
も$guardで渡ってきたものも追加してリダイレクトする。
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class RedirectIfAuthenticated
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string|null $guard
* @return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
return redirect($guard . '/home');
}
return $next($request);
}
}
ログインが成功した時のリダイレクト先。これもリダイレクト先に$guardを付けてあげる。
Controller
public function __construct()
{
$this->redirectTo = request('appCode') . '/home'; // ログイン後のリダイレクト先
$this->redirectAfterLogout = request('appCode') . '/login'; // ログアウト後のリダイレクト先
// routes.php側でログイン指定している。
//$this->middleware($this->guestMiddleware(), ['except' => 'logout']);
}
protected $redirectTo = ‘/home’;
ってプロパティでもいいらしいが、動的に変えたかったのでコントラクタで指定する。
request(‘appCode’)はどっかのミドルウェアでurlのプレフィックスを取得している。
作ったあとなので記載に漏れがあるかもだけど、こんな感じでなんとか行けたと思う。
もう疲れたので、この辺で注意事項を書いとこ。
その他
あと、パスワードリマインダのメール本文はこのファイル。
/resources/views/auth/emails/password.blade.php
件名はどこやねん!って思ったら、これ。
public function __construct()
{
$this->redirectPath = request('appCode') . '/logout'; // パスワード変更後のリダイレクト先
$this->subject = 'パスワードリセット';
//$this->middleware($this->guestMiddleware());
}
認証時のエラーメッセージはこのファイル
/resources/lang/ja/auth.php
パスワードリマインダのエラーメッセージはこのファイル
/resources/lang/ja/passwords.php
メール送信は.envが使われず、/config/mail.phpが使われる。どっちかに統一せーや!!!
今回は9,000文字強。。。なかなかの大作。はしょったけど。笑