Laravel 5.6 で、userテーブル以外で認証を行う

Laravelを使って、特定ページに認証をつけることにした。

パスワードを知っている人だけが、そのページに入ることができるように。

 

そのページは、DBのviewerというテーブルにパスワードを設定しており、

そのviewerテーブルを使って認証を行うようにした。

各ページ毎にパスワードが異なっており、あるページで認証が通っても、別のページでは認証が通らないようにする。

またパスワードがついていないページは、認証なしで見ることができる。

 

(参考)

Laravelで複数テーブルを使ったログイン認証を実装する - Qiita

 

1.config/auth.php 

'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],

'api' => [
'driver' => 'token',
'provider' => 'users',
],
//以下を追加
'viewuser' => [
'driver' => 'session',
'provider' => 'viewusers',
],
],
 
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
//以下を追加
'viewusers' => [
'driver' => 'eloquent',
'model' => App\Viewer::class,
],
],

※パスワードの再送は設定しないため、'passwords'は追加していない

 

2.web.php

URL遷移のイメージ

//初期アクセス http://hogehoge/viewer/XXXXXXXXXX
Route::get('viewer/{page_id}',
'ViewAuth\LoginController@index')->name('viewurl');
 
//パスワードが付いている場合、ログイン画面へ
Route::get('viewer/login/{page_id}',
'ViewAuth\LoginController@showLoginForm')->name('viewlogin');
 
//ログイン認証
Route::post('viewer/login',
'ViewAuth\LoginController@authenticate')->name('viewpostlogin');

 

※Laravelのページで分かりにくかったが、通常の認証では、ログイン認証は、コントローラ@login を使う。

しかし、独自認証を行う場合、コントローラ@authenticateとして、コントローラ内にatuthenticate()を書く。

認証 5.3 Laravel

 

3.app/Viewer.php

通常のモデルは、

class Viewer extends Model

となっているが、このままでは認証に使うことができない。

よって、認証に使うモデル(ここでは、Viewer)は、以下のようにする。

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Auth\User as Authenticatable;//認証用に追加

//class Viewer extends Model
class Viewer extends Authenticatable//User.phpに合わせて変更
{
protected $table = 'Viewer';
protected $fillable = [
'page_id',
'password',
・・・
・・・
];
protected $hidden = [
'password',
];
}

 

4.app/Http/Middleware/RedirectIfAuthenticated.php

認証が完了した場合、通所は所定のページにリダイレクトされるようになっている。

しかし、私の場合、リダイレクト処理はコントローラ内で書くようにしたかったため、以下のようにして、認証後のリダイレクトを止めるようにした。

public function handle($request, Closure $next, $guard = null)
{
//変更。オリジナルは以下。
//if (Auth::guard($guard)->check()) {
// return redirect('/home');
//}
if (Auth::guard($guard)->check()) {
if ($guard=='viewuser') { //ここを追加
//viewuserの認証時は、認証を通った後もリダイレクトしない
} else {
return redirect('/home');
}
}
  return $next($request);
}

 

5.app/Http/Controllers/ViewAuth/LoginController.php

参考にしてください。

<?php

//namespace App\Http\Controllers\Auth; //コメントアウト
namespace App\Http\Controllers\ViewAuth; // 追加

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;

use Illuminate\Http\Request;// 追加
use Illuminate\Support\Facades\Auth;// 追加
use App\Viewer;//追加
use Validator;//追加

class LoginController extends Controller
{
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/

use AuthenticatesUsers;

/**
* Where to redirect users after login.
*
* @var string
*/
//protected $redirectTo = '/viewer';//変更

/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
//$this->middleware('guest')->except('logout');
$this->middleware('guest:viewuser')->except('logout');//変更
}
 
//以下追加
protected function guard()
{
return Auth::guard('viewuser'); //config/auth.phpで追加したguardを指定
}

//初期アクセス時。または認証後のアクセス時
public function index($page_id)
//$page_idは、web.phpの中で、Route::get('viewer/{page_id}'
//として指定している変数
{
$ninsyou = 0;//認証フラグ
//そのページにパスワードがついているかどうかを調べる
$password = Viewer::where('page_id', $page_id)->first();

if ($password->password != NULL) {//パスワードありの場合
if (Auth::guard('viewuser')->check()) { //認証済みの場合の処理。
$user = Auth::guard('viewuser')->user();
//guard('viewuser')のため、viewerテーブルのレコードが返される。
if ($user->page_id == $page_id) {
$ninsyou = 1; //認証OK
} else {
//違うページで認証は通っていたが、このページでは認証が通っていない場合
$ninsyou = 0;
}
} else { //未認証の場合の処理
$ninsyou = 0;
}
} else {//パスワードがない場合、そのままビュー画面へいく
$ninsyou = 1; //認証OK
}

if ($ninsyou==1) {
$this->view($page_id);
} else {
//ログインページへリダイレクト
return redirect()->route('viewlogin', ['page_id' => $page_id]);
}
}

//認証ページの表示
//$requestは、認証失敗時にGETでついてくるpass_eroorを取るために必要。
//$page_idは、web.phpで指定している、Route::get('viewer/login/{page_id}'の部分。
public function showLoginForm(Request $request, $page_id)
{
//function authenticate()で認証に失敗すると、
//redirect()でpass_error=1が付いてくる。
$pass_error = $request->input('pass_error');
 
return view('viewer.viewerlogin',
['page_id'=>$page_id, 'pass_error'=>$pass_error]);
}

//自前の認証
public function authenticate(Request $request)
{
//validatorを指定しないとエラーになる
$validator = Validator::make($request->all(), [
'page_id' => 'required|unique:posts',
'password' => 'required',
]);

Auth::guard('viewuser');

$page_id = $request->input('page_id');
$password = $request->input('password');

if (Auth::guard('viewuser')
->attempt(['page_id' => $page_id, 'password' => $password])) {
logger('認証成功!');
//閲覧ページを表示
return redirect()->route('viewurl',['page_id' => $page_id]);
} else {
logger('認証失敗');
//ログインページに戻る
return redirect()->route('viewlogin', ['page_id' => $page_id, 'pass_error'=>1]);
}
}

public function view($page_id)
{
認証後の閲覧ページの処理;
}

}

 

以上、ご参考まで。