[Laravel]マルチ認証機能がうまくいかない
解決したいこと
[Laravel]マルチ認証機能がうまくいかない
うまくいかないところが2つあり、
○マルチ認証を開発しているのですが、認証ページでデータベースに登録しているメールアドレス、パスワードを用いてログインしようとしても認証されません。
○またログインしていないときの強制リダイレクトができません
こちらのサイトを利用して実装しました。
https://blog.capilano-fw.com/?p=8159
環境Laravel8、MAMPでApcheを利用、Mysqlを用いてモバイルオーダーアプリを作りました。
ログイン機能はJetstreamを利用しており、マルチ認証機能を実装しようとしています。
発生している問題・エラー
正しく認証しない
2つのユーザーデータを作り、ログインしようとしましたが、うまくログインができませんでした。
multi_login画面で管理者ではない選択でUserログインはうまくいきましたが、管理者ログインはできていません。
例)
Controller
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class MultiAuthController extends Controller
{
public function showLoginForm() {
return view('multi_auth.login');
}
public function index() {
return 'OK';
}
public function login(Request $request) {
$credentials = $request->only(['email', 'password']);
$guard = $request->guard;
if(\Auth::guard($guard)->attempt($credentials)) {
return redirect($guard .'/dashboard'); // ログインしたらリダイレクト
}
return back()->withErrors([
'auth' => ['認証に失敗しました']
]);
}
}
ログインしていないときの強制リダイレクト
<?php
namespace App\Http\Middleware;
use Illuminate\Auth\Middleware\Authenticate as Middleware;
use Illuminate\Support\Str;
class Authenticate extends Middleware
{
/**
* Get the path the user should be redirected to when they are not authenticated.
*
* @param \Illuminate\Http\Request $request
* @return string|null
*/
protected function redirectTo($request)
{
if (! $request->expectsJson()) {
$uri = $request->path();
// URIが以下3つから始まる場合
if(Str::startsWith($uri, ['administrators/'])) {
return 'multi_login';
}
return route('login');
}
}
}
Model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Auth\User as Authenticatable;
class Administrator extends Authenticatable
{
use HasFactory;
}
configファイルの認証
<?php
return [
/*
|--------------------------------------------------------------------------
| Authentication Defaults
|--------------------------------------------------------------------------
|
| This option controls the default authentication "guard" and password
| reset options for your application. You may change these defaults
| as required, but they're a perfect start for most applications.
|
*/
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
/*
|--------------------------------------------------------------------------
| Authentication Guards
|--------------------------------------------------------------------------
|
| Next, you may define every authentication guard for your application.
| Of course, a great default configuration has been defined for you
| here which uses session storage and the Eloquent user provider.
|
| All authentication drivers have a user provider. This defines how the
| users are actually retrieved out of your database or other storage
| mechanisms used by this application to persist your user's data.
|
| Supported: "session", "token"
|
*/
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
'hash' => false,
],
'administrators' => [
'driver' => 'session',
'provider' => 'administrators',
],
],
/*
|--------------------------------------------------------------------------
| User Providers
|--------------------------------------------------------------------------
|
| All authentication drivers have a user provider. This defines how the
| users are actually retrieved out of your database or other storage
| mechanisms used by this application to persist your user's data.
|
| If you have multiple user tables or models you may configure multiple
| sources which represent each model / table. These sources may then
| be assigned to any extra authentication guards you have defined.
|
| Supported: "database", "eloquent"
|
*/
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
'administrators' => [
'driver' => 'eloquent',
'model' => App\Models\Administrator::class,
]
// 'users' => [
// 'driver' => 'database',
// 'table' => 'users',
// ],
],
/*
|--------------------------------------------------------------------------
| Resetting Passwords
|--------------------------------------------------------------------------
|
| You may specify multiple password reset configurations if you have more
| than one user table or model in the application and you want to have
| separate password reset settings based on the specific user types.
|
| The expire time is the number of minutes that the reset token should be
| considered valid. This security feature keeps tokens short-lived so
| they have less time to be guessed. You may change this as needed.
|
*/
'passwords' => [
'users' => [
'provider' => 'users',
'table' => 'password_resets',
'expire' => 60,
'throttle' => 60,
],
],
/*
|--------------------------------------------------------------------------
| Password Confirmation Timeout
|--------------------------------------------------------------------------
|
| Here you may define the amount of seconds before a password confirmation
| times out and the user is prompted to re-enter their password via the
| confirmation screen. By default, the timeout lasts for three hours.
|
*/
'password_timeout' => 10800,
];
<html>
<head>
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
</head>
<body>
<form method="POST" action="multi_login">
@csrf
<div class="p-3">
@error('auth')
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-3">
⚠ {{ $message }}
</div>
@enderror
<label class="block">メールアドレス</label>
<input class="border rounded mb-3 px-2 py-1" type="text" name="email">
<label class="block">パスワード</label>
<input class="border rounded mb-3 px-2 py-1" type="password" name="password">
<label class="block">ユーザータイプ</label>
<select name="guard" class="border rounded px-2 py-1 mb-5">
<option value="">▼選択してください</option>
<option value="administrators">管理者</option>
</select>
<br>
<button class="bg-blue-500 text-white rounded px-3 py-2" type="submit">ログイン</button>
</div>
</form>
</body>
</html>
認証関連のルーティング情報はこちらです
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\HelloController;
use App\Http\Middleware\HelloMiddleware;
use App\Http\Controllers\PersonController;
use App\Http\Controllers\PurchasehistoryController;
use App\Http\Controllers\BoardController;
use App\Http\Controllers\RestappController;
use App\Http\Controllers\ProductController;
use App\Http\Controllers\StoreController;
use App\Http\Controllers\CartController;
use App\Http\Controllers\MultiAuthController;
use App\Http\Controllers\ShopController;
use Illuminate\Support\Facades\Mail;
use App\Mail\Thanks;
Route::middleware(['auth:sanctum', 'verified'])->get('/dashboard', function () {
return view('dashboard');
})->name('dashboard');
Route::get('multi_login', [MultiAuthController::class, 'showLoginForm']);
Route::post('multi_login', [MultiAuthController::class, 'login']);
// ログアウト
Route::get('multi_login/logout', [MultiAuthController::class, 'logout']);
// ログイン後のページ
Route::prefix('administrators')->middleware('auth:administrators')->group(function(){
Route::get('dashboard', function(){ return '管理者でログイン完了'; });
Route::get('home', [MultiAuthController::class, 'index']);
});
データベースはこちらです。
administrators
administrators/homeに行くとログインせずにOKが出てしまいます。
追加
Controllerをいじるとうまくいきましたが、1つのエラーが出ました。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class MultiAuthController extends Controller
{
public function showLoginForm() {
return view('multi_auth.login');
}
public function index() {
return 'OK';
}
public function login(Request $request) {
$credentials = $request->only(['email', 'password']);
$guard = $request->guard;
if(Auth::guard($guard)->attempt($credentials)) {
return redirect($guard .'/dashboard'); // ログインしたらリダイレクト
}
return back()->withErrors([
'auth' => ['認証に失敗しました']
]);
}
}
エラーが出ました。
Undefined method 'attempt'.
attemptはうまく動いてないようです?