中间件

HTTP 中间件

介绍

HTTP 中间件为即将进入应用程序的请求提供了一种方便的过滤机制。例如,Lumen 包含一个验证用户是否已通过认证的中间件。如果用户未通过认证,中间件将重定向到登录页面。如果用户已经通过认证,那么该中间件将允许请求进一步进入应用程序。

当然了,除了身份验证外,还可以自定义中间件来执行更多的任务。CORS 中间件将会在返回响应时添加合适的头信息。日志中间件记录进入应用程序的请求。

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

自定义中间件

可以复制 Lumen 应用中自带的 ExampleMiddleware 来创建一个新的中间件。这里我们定义允许 age 大于200的请求进一步传递到应用程序中,否则重定向到 “home” URI。

<?php

namespace App\Http\Middleware;

use Closure;

class OldMiddleware
{
    /**
     * Run the request filter.
     *
     * @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,中间件会将本次请求重定向到客户端。否则,该请求将进一步传递到应用程序中。允许请求进一步进入应用程序,只需使用 $request 调用 $next 回调即可。

最好将「中间件」设想为 HTTP 请求到达您的应用程序所必须经过的一系列「层」。每一层都可以检查请求,甚至完全拒绝它。

Before / After 中间件

中间件在请求被处理之前还是之后执行,完全取决于中间件自身。例如,下面的中间件将会在请求被应用程序处理之前执行一些任务操作。

<?php

namespace App\Http\Middleware;

use Closure;

class BeforeMiddleware
{
    public function handle($request, Closure $next)
    {
        // Perform action

        return $next($request);
    }
}

接下来,这个中间件将会在请求被应用程序处理之后执行一些任务操作。

<?php

namespace App\Http\Middleware;

use Closure;

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

        // Perform action

        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内核中定义了中间件后,就可以在路由的可选数组中使用该中间件:

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

你也可以一次为路由指定多个中间件:

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

或者,在使用 uses 键指定控制器操作的路由中,添加控制器路由中间件:

$router->get('admin/profile', [
    'middleware' => 'auth',
    'uses' => 'AdminController@showProfile'
]);

中间件参数

中间件可以接受额外的自定义参数。例如,如果你想在执行相应的操作之前验证经过认证的用户是否拥有给定的「角色」,可以创建一个 RoleMiddleware 中间件,该中间件接受一个角色名称作为额外的参数。

额外的中间件参数将会在中间件参数 $next 之后传入。

<?php

namespace App\Http\Middleware;

use Closure;

class RoleMiddleware
{
    /**
     * Run the request filter.
     *
     * @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)) {
            // Redirect...
        }

        return $next($request);
    }

}

在定义路由时,可以通过用 : 分隔中间件名称和参数来指定中间件参数。多个参数应以逗号分隔:

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

Terminable 中间件

有时候我们在 HTTP 响应发送浏览器之后,还需要做一些操作。例如,session 中间件就是在响应发送浏览器之后才存储 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)
    {
        // Store the session data...
    }
}

terminate 方法接受两个参数,一个是请求实例,一个是响应实例。不过我们需要将 terminate 中间件添加到 bootstrap/app.php 文件的全局中间件列表中。

当调用 terminate 方法时,Lumen 将会从服务容器中解析出一个全新的中间件实例。如果在中间件的 handleterminate 方法中使用相同的中间件实例,需要通过容器的 singleton 方法在容器中注册中间件。

本文章首发在 LearnKu.com 网站上。

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
上一篇 下一篇
Summer
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
贡献者:4
讨论数量: 0
发起讨论 只看当前版本


暂无话题~