Laravel5.5+ 區分前後端使用者登入
Laravel 的使用者認證是通過 Auth Facade 門臉實現的,手動認證可是使用 Auth::login() 或 Auth::attempt() 這兩個方法實現.
以下內容純屬個人實現,也許有更優的實現方式.
對於識別前後端的使用者,可以使用 Auth::guard() 方法實現,前端預設為 web 看守,Auth::guard('web') ,後端使用者使用 admin 看守, Auth::guard('admin') .
1.新建 guard 看守
在 config/auth.php 中新建 admin 看守
'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'token', 'provider' => 'users', ], 'admin' => [ 'driver' => 'session', 'provider' => 'users' ] ]
看守的提供者 provider 不變,還是 users .
'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App\Models\User::class, 'table' => 'users', ], // 'users' => [ // 'driver' => 'database', // 'table' => 'users', // ], ],
這樣做的好處是前後端的使用者可以放在一張 users 表中,只需要利用狀態區分使用者就好了,比如 user_status = 1 的是前端使用者, user_status = 2 的是後端使用者.
2. 新建兩個中介軟體,區分前後端使用者登入
將新建的中介軟體新增到 app/Http/Kernel.php 中
protected $routeMiddleware = [ .... 'adminVerify' => \App\Http\Middleware\AdminVerify::class, 'frontVerify' => \App\Http\Middleware\FrontVerify::class, ];
在區分前後端使用者登入這個功能中,可以廢棄預設 Auth 認證中介軟體 guest.
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
這樣做的好處是簡化了中介軟體的使用,不用兩套系統公用一個 guest 中介軟體.
我們使用 adminVerify 中介軟體來做後端認證,所有的後端路由都必須通過這個中介軟體. adminVerify 中介軟體如下
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class AdminVerify
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$current_uri = $request->getRequestUri();
$ignore_uri = [
'/admin/login',
'/admin/logout'
];
if (in_array($current_uri, $ignore_uri)) {
return $next($request);
} else {
if (Auth::guard('admin')->check()) {
return $next($request);
} else {
return redirect('/admin/login');
}
}
}
}
使用 frontVerify 中介軟體來做前端認證,所有的前端路由都必須通過這個中介軟體. frontVerify 中介軟體如下
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class FrontVerify
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$current_uri = $request->getRequestUri();
$ignore_uri = [
'/login',
'/logout'
];
if (in_array($current_uri, $ignore_uri)) {
return $next($request);
} else {
if (Auth::guard('web')->check()) {
return $next($request);
} else {
return redirect('/login');
}
}
}
}
3. 路由設定
預設所有的前端路由都沒有字首,所有的後端路由都帶有 admin 字首. 路由設定如下.
// ==== 前後端登入
// 前端
Route::group(['middleware' => ['frontVerify']], function () {
Route::get('/', 'Front\[email protected]')->name('front_index');
Route::get('login', 'Front\[email protected]');
Route::post('login', 'Front\[email protected]')->name('front_login');
Route::get('logout', 'Front\[email protected]')->name('front_logout');
Route::get('login-success', 'Front\[email protected]')->name('front_success');
});
// 後端
Route::group(['prefix' => 'admin', 'middleware' => ['adminVerify']], function () {
Route::get('/', 'Admin\[email protected]')->name('admin_index');
Route::get('login', 'Admin\[email protected]');
Route::post('login', 'Admin\[email protected]')->name('admin_login');
Route::get('logout', 'Admin\[email protected]')->name('admin_logout');
Route::get('login-success', 'Admin\[email protected]')->name('admin_success');
});
// ==== 前後端登入 END
前後端都有一個 login-success 頁面,這兩個頁面的內容是一模一樣的,除了文字不一樣.
以下是後端頁面的 login-success 頁面
<h1>後端登入成功</h1>
我是 admin guard -- {{ \Illuminate\Support\Facades\Auth::guard('admin')->check() }}
=====
我是 web guard -- {{ \Illuminate\Support\Facades\Auth::guard('web')->check() }}
前端的 login-success 頁面
<h1>前端登入成功</h1>
我是 admin guard -- {{ \Illuminate\Support\Facades\Auth::guard('admin')->check() }}
=====
我是 web guard -- {{ \Illuminate\Support\Facades\Auth::guard('web')->check() }}
路由列表中前端有一個首頁 / ,後端也有一個預設的首頁 /admin/,這兩個首頁的作用是驗證未登入的使用者是不能訪問前後端的任何一個頁面的,如果通過路由訪問,並且是在沒有登入的情況下,那麼在中介軟體中就讓其自動跳到對應的登入頁面,具體可以看中介軟體的程式碼.
4 . 具體登入程式碼實現
4.1.1 前端登入
<?php
namespace App\Http\Controllers\Front;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class LoginController extends Controller
{
//
use AuthenticatesUsers;
/**
* LoginController constructor.
*/
public function __construct()
{
}
public function index()
{
return view('front.index');
}
public function login(Request $request)
{
return view('front.login');
}
public function store(Request $request)
{
$credentials = $this->validate($request, [
'phone' => 'required|max:255',
'password' => 'required'
]);
$rs = $this->guard()->attempt($credentials);
if ($rs) {
return redirect()->route('front_success');
} else {
return back();
}
}
public function logout(Request $request)
{
$this->guard()->logout();
$request->session()->flush();
return redirect()->route('front_login');
}
public function success(Request $request)
{
return view('front.success');
}
protected function guard()
{
return Auth::guard('web');
}
}
4.1.2 後端登入
<?php
/**
* Created by PhpStorm.
* User: nwei
* Date: 2018/12/21
* Time: 16:19
*
* .--, .--,
* ( ( \.---./ ) )
* '.__/o o\__.'
* {= ^ =}
* > - <
* / \
* // \\
* //| . |\\
* "'\ /'"_.-~^`'-.
* \ _ /--' `
* ___)( )(___
* (((__) (__))) 高山仰止,景行行止.雖不能至,心嚮往之.
*/
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class LoginController extends Controller
{
/**
* LoginController constructor.
* @param string $redirectTo
*/
public function __construct()
{
}
public function index()
{
return view('admin.index');
}
public function login()
{
return view('admin.login');
}
public function store(Request $request)
{
$credentials = $this->validate($request, [
'phone' => 'required|max:255',
'password' => 'required'
]);
$rs = $this->guard()->attempt($credentials);
if ($rs) {
return redirect()->route('admin_success');
} else {
return back();
}
}
public function success()
{
return view('admin.success');
}
public function logout(Request $request)
{
$this->guard()->logout();
$request->session()->flush();
return redirect('admin/login');
}
protected function guard()
{
return Auth::guard('admin');
}
}
4.2 登入結果
4.2.1 前端登入結果
4.2.2 開一個隱身模式,測試後端登入結果
測試成功!