中间件

HTTP 中间件

简介

HTTP 中间件提供了一个方便的机制来过滤进入应用程序的 HTTP 请求。例如,Lumen 内置了一个中间件来验证用户的身份认证。如果用户未通过身份验证,中间件将会把用户导向登录页面,反之,当用户通过了身份验证,中间件将会通过此请求并接着往下执行。

当然,除了身份验证之外,中间件也可以被用来运行各式各样的任务,如:CORS 中间件负责替所有即将离开程序的响应加入适当的标头;而日志中间件则可以记录所有传入应用程序的请求。

所有的中间件都放在 app/Http/Middleware 目录内。

定义中间件

你可以通过复制 Lumen 内置的示例文件 ExampleMiddleware 来创建一个中间件。在这个中间件中,我们只允许参数 age 大于 200 的请求才能够访问该路由。 否则,我们将此用户重定向到首页 "home" 这个 URI 上。

<?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 重定向到客户端;否则,请求将进一步传递到应用中。要让请求继续传递到应用程序中 (即允许 " 通过 " 中间件验证的),只需使用 $request 作为参数去调用回调函数 $next

最好将中间件想象为一系列 HTTP 请求必须经过才能进入你应用的 " 层 " 。每一层都会检查请求(是否符合某些条件),(如果不符合)甚至可以(在请求访问你的应用之前)完全拒绝掉。

前置 / 后置 中间件

中间件是在请求之前或之后运行取决于中间件本身。例如, 接下来的这个中间件将在应用处理请求 before 执行其任务:

<?php

namespace App\Http\Middleware;

use Closure;

class BeforeMiddleware
{
    public function handle($request, Closure $next)
    {
        // 执行操作

        return $next($request);
    }
}

而接下来的这个中间件将在应用处理请求 之后 执行其任务:

<?php

namespace App\Http\Middleware;

use Closure;

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

        // 执行操作

        return $response;
    }
}

注册中间件

全局中间件

若是希望中间件在应用处理每个 HTTP 请求期间运行,只需要在 bootstrap/app.php 文件中的 $app->middleware() 方法中列出这个中间件:

$app->middleware([
   App\Http\Middleware\OldMiddleware::class
]);

为路由分配中间件

如果你想将中间件分配给特定的路由,首先需要在 bootstrap/app.php 文件中调用 $app->routeMiddleware() 方法时为中间件分配一个简短的键:

$app->routeMiddleware([
    'auth' => App\Http\Middleware\Authenticate::class,
]);

一旦在 HTTP 内核中定义好了中间件,就可以在路由选项内使用 middleware 键:

$router->get('admin/profile', ['middleware' => 'auth', function () {
    //
}]);

可以使用数组为路由指定多个中间件:

$router->get('/', ['middleware' => ['first', 'second'], function () {
    //
}]);

中间件参数

中间件也可以接收自定义传参,例如,要在运行特定操作前检查已验证用户是否具备该操作的 " 角色 " ,可以创建 RoleMiddleware 来接收角色名称作为额外的传参。

附加的中间件参数将会在 $next 参数之后被传入中间件:

<?php

namespace App\Http\Middleware;

use Closure;

class RoleMiddleware
{
    /**
     * 运行请求过滤
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @param  string  $role
     * @return mixed
     */
    public function handle($request, Closure $next, $role)
    {
        if (! $request->user()->hasRole($role)) {
            // 重定向...
        }

        return $next($request);
    }

}

在路由中可使用冒号 :. 来区隔中间件名称与指派参数,多个参数可使用逗号作为分隔:

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

Terminable 中间件

有时中间件可能需要在 HTTP 响应发送到浏览器之后处理一些工作。例如, "session" 中间件会在响应发送到浏览器之后将会话数据写入存储器中。想要做到这一点,你需要定义一个名为 "terminable" 的中间并添加一个 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 方法应该同时接收和响应。一旦定义了这个中间件,你应该将它添加到路由列表或 bootstrap/app.php 文件的全局中间件中。

在你的中间件上调用 terminate 调用时,Lumen 会从 服务容器中解析出一个新的中间件实例。如果你希望在 handleterminate 方法被调用时使用一致的中间件实例,只需在容器中使用容器的 singleton 方法注册中间件。

本文章首发在 LearnKu.com 网站上。
上一篇 下一篇
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
贡献者:2
讨论数量: 0
发起讨论 只看当前版本


暂无话题~