鍍金池/ 教程/ PHP/ HTTP 中間件
門面
Laravel Homestead
安裝及配置
測試
HTTP 中間件
加密
升級指南
幫助函數
應用目錄結構
集合
新手入門指南-簡單任務管理系統
任務調度
查詢構建器
視圖
驗證
Laravel Cashier(訂購&支付&發(fā)票)
本地化
隊列
調整器
分頁
文件系統/云存儲
貢獻代碼
哈希
HTTP 控制器
緩存
遷移
HTTP 請求
Laravel Elixir
發(fā)行版本說明
Envoy 任務運行器(SSH任務)
序列化
Session
起步
帶用戶功能的任務管理系統
起步
用戶授權
郵件
事件
填充數據
HTTP 路由
服務提供者
Blade 模板引擎
包開發(fā)
用戶認證
Artisan 控制臺
HTTP 響應
集合
服務容器
關聯關系
一次請求的生命周期
契約
Redis
錯誤&日志

HTTP 中間件

1、簡介

HTTP 中間件提供了一個便利的機制來過濾進入應用的 HTTP 請求。例如,Laravel 包含了一個中間件來驗證用戶是否經過授權,如果用戶沒有經過授權,中間件會將用戶重定向到登錄頁面,否則如果用戶經過授權,中間件就會允許請求繼續(xù)往前進入下一步操作。

當然,除了認證之外,中間件還可以被用來處理更多其它任務。比如:CORS 中間件可以用于為離開站點的響應添加合適的頭(跨域);日志中間件可以記錄所有進入站點的請求。

Laravel 框架內置了一些中間件,包括維護模式中間件、認證、CSRF 保護中間件等等。所有的中間件都位于 app/Http/Middleware 目錄。

2、定義中間件

想要創(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 重定向到客戶端;否則,請求會被傳遞下去。將請求往下傳遞可以通過調用回調函數 $next。

理解中間件的最好方式就是將中間件看做 HTTP 請求到達目標之前必須經過的“層”,每一層都會檢查請求甚至會完全拒絕它。

2.1 中間件之前/之后

一個中間件是否請求前還是請求后執(zhí)行取決于中間件本身。比如,以下中間件會在請求處理前執(zhí)行一些任務:

<?php

namespace App\Http\Middleware;

use Closure;

class BeforeMiddleware
{
    public function handle($request, Closure $next)
    {
        // 執(zhí)行動作

        return $next($request);
    }
}

然而,下面這個中間件則會在請求處理后執(zhí)行其任務:

<?php

namespace App\Http\Middleware;

use Closure;

class AfterMiddleware
{
    public function handle($request, Closure $next)
    {
        $response = $next($request);

        // 執(zhí)行動作

        return $response;
    }
}

3、注冊中間件

3.1 全局中間件

如果你想要中間件在每一個 HTTP 請求期間被執(zhí)行,只需要將相應的中間件類放到 app/Http/Kernel.php 的數組屬性$middleware 中即可。

3.2 分配中間件到路由

如果你想要分配中間件到指定路由,首先應該在 app/Http/Kernel.php 文件中分配給該中間件一個簡寫的 key,默認情況下,該類的$routeMiddleware 屬性包含了 Laravel 內置的入口中間件,添加你自己的中間件只需要將其追加到后面并為其分配一個 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 中被定義后,可以在路由選項數組中使用$middleware 鍵來指定中間件:

Route::get('admin/profile', ['middleware' => 'auth', function () {
    //
}]);

4、中間件參數

中間件還可以接收額外的自定義參數,比如,如果應用需要在執(zhí)行動作之前驗證認證用戶是否擁有指定的角色,可以創(chuàng)建一個 RoleMiddleware 來接收角色名作為額外參數。 額外的中間件參數會在$next 參數之后傳入中間件:

<?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);
    }

}

中間件參數可以在定義路由時通過:分隔中間件名和參數名來指定,多個中間件參數可以通過逗號分隔:

Route::put('post/{id}', ['middleware' => 'role:editor', function ($id) {
    //
}]);

5、可終止的中間件

有時候中間件可能需要在 HTTP 響應發(fā)送到瀏覽器之后做一些工作。比如,Laravel 內置的“session”中間件會在響應發(fā)送到瀏覽器之后將 session 數據寫到存儲器中,為了實現這個,定義一個可終止的中間件并添加 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 數據...
    }
}

terminate 方法將會接收請求和響應作為參數。一旦你定義了一個可終止的中間件,應該將其加入到 HTTP kernel 的全局中間件列表中。 當調用中間件上的 terminate 方法時,Laravel 將會從服務容器中取出該中間件的新的實例,如果你想要在調用 handleterminate 方法時使用同一個中間件實例,則需要使用容器的 singleton 方法將該中間件注冊到容器中。

上一篇:序列化下一篇:Session