HTTP。例如,Laravel包含了一個中間件來驗證用戶是否經(jīng)過授權(quán),如果用戶沒有經(jīng)過授權(quán),中間件會將用戶重定向到登錄頁面,否則如果用戶經(jīng)過授權(quán),中間件就會允許請求繼續(xù)往前進入下一步操作。
當(dāng)然,除了認(rèn)證之外,中間件還可以被用來處理更多其它任務(wù)。比如:CORS中間件可以用于為離開站點的響應(yīng)添加合適的頭(跨域);日志中間件可以記錄所有進入站點的請求。
Laravel框架內(nèi)置了一些中間件,包括維護模式中間件、認(rèn)證、CSRF保護中間件等等。所有的中間件都位于app/Http/Middleware
目錄。
想要創(chuàng)建一個新的中間件,可以通過Artisan命令make:middleware
:
php artisan make:middleware OldMiddleware
這個命令會在app/Http/Middleware
目錄下創(chuàng)建一個新的中間件類OldMiddleware
,在這個中間件中,我們只允許提供的age大于200的訪問路由,否則,我們將用戶重定向到主頁:
<?php
namespace App\Http\Middleware;
use Closure;
class OldMiddleware
{
/**
* 返回請求過濾器
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if ($request->input('age') <= 200) {
return redirect('home');
}
return $next($request);
}
}
正如你所看到的,如果age<=200
,中間件會返回一個HTTP重定向到客戶端;否則,請求會被傳遞下去。將請求往下傳遞可以通過調(diào)用回調(diào)函數(shù)$next
。
理解中間件的最好方式就是將中間件看做HTTP請求到達(dá)目標(biāo)之前必須經(jīng)過的“層”,每一層都會檢查請求甚至?xí)耆芙^它。
一個中間件是否請求前還是請求后執(zhí)行取決于中間件本身。比如,以下中間件會在請求處理前執(zhí)行一些任務(wù):
<?php
namespace App\Http\Middleware;
use Closure;
class BeforeMiddleware
{
public function handle($request, Closure $next)
{
// 執(zhí)行動作
return $next($request);
}
}
然而,下面這個中間件則會在請求處理后執(zhí)行其任務(wù):
<?php
namespace App\Http\Middleware;
use Closure;
class AfterMiddleware
{
public function handle($request, Closure $next)
{
$response = $next($request);
// 執(zhí)行動作
return $response;
}
}
如果你想要中間件在每一個HTTP請求期間被執(zhí)行,只需要將相應(yīng)的中間件類放到app/Http/Kernel.php
的數(shù)組屬性$middleware
中即可。
如果你想要分配中間件到指定路由,首先應(yīng)該在app/Http/Kernel.php
文件中分配給該中間件一個簡寫的key,默認(rèn)情況下,該類的$routeMiddleware
屬性包含了Laravel內(nèi)置的入口中間件,添加你自己的中間件只需要將其追加到后面并為其分配一個key:
// 在 App\Http\Kernel 里中
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,];
中間件在HTTP kernel中被定義后,可以在路由選項數(shù)組中使用$middleware
鍵來指定中間件:
Route::get('admin/profile', ['middleware' => 'auth', function () {
//
}]);
中間件還可以接收額外的自定義參數(shù),比如,如果應(yīng)用需要在執(zhí)行動作之前驗證認(rèn)證用戶是否擁有指定的角色,可以創(chuàng)建一個RoleMiddleware
來接收角色名作為額外參數(shù)。
額外的中間件參數(shù)會在$next參數(shù)之后傳入中間件:
<?php
namespace App\Http\Middleware;
use Closure;
class RoleMiddleware
{
/**
* 運行請求過濾器
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string $role
* @return mixed
* translator http://laravelacademy.org
*/
public function handle($request, Closure $next, $role)
{
if (! $request->user()->hasRole($role)) {
// Redirect...
}
return $next($request);
}
}
中間件參數(shù)可以在定義路由時通過:分隔中間件名和參數(shù)名來指定,多個中間件參數(shù)可以通過逗號分隔:
Route::put('post/{id}', ['middleware' => 'role:editor', function ($id) {
//
}]);
有時候中間件可能需要在HTTP響應(yīng)發(fā)送到瀏覽器之后做一些工作。比如,Laravel內(nèi)置的“session”中間件會在響應(yīng)發(fā)送到瀏覽器之后將session數(shù)據(jù)寫到存儲器中,為了實現(xiàn)這個,定義一個可終止的中間件并添加terminate
方法到這個中間件:
<?php
namespace Illuminate\Session\Middleware;
use Closure;
class StartSession
{
public function handle($request, Closure $next)
{
return $next($request);
}
public function terminate($request, $response)
{
// 存儲session數(shù)據(jù)...
}
}
terminate
方法將會接收請求和響應(yīng)作為參數(shù)。一旦你定義了一個可終止的中間件,應(yīng)該將其加入到HTTP kernel的全局中間件列表中。
當(dāng)調(diào)用中間件上的terminate
方法時,Laravel將會從服務(wù)容器中取出該中間件的新的實例,如果你想要在調(diào)用handle
和terminate
方法時使用同一個中間件實例,則需要使用容器的singleton
方法將該中間件注冊到容器中。
更多建議: