介绍
HTTP中间件提供了一种方便的机制,用于过滤进入您的应用程序的HTTP请求。例如,Lumen包含一个中间件,该中间件可验证您的应用程序的用户是否已通过身份验证。如果用户未通过身份验证,则中间件会将用户重定向到登录屏幕。但是,如果用户通过了身份验证,则中间件将允许请求进一步进入应用程序。
当然,除了身份验证之外,还可以编写其他中间件来执行各种任务。CORS中间件可能负责向离开您的应用程序的所有响应中添加适当的标头。记录中间件可能会将所有传入请求记录到您的应用程序中。
所有中间件都应存储在app/Http/Middleware
目录中。
定义中间件
要创建新的中间件,请复制ExampleMiddleware
默认Lumen应用程序随附的。在新的中间件中,仅当提供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
,则中间件将向客户端返回HTTP重定向;否则,中间件将返回HTTP重定向。否则,该请求将进一步传递到应用程序中。要将请求更深地传递到应用程序中(允许中间件“传递”),只需使用调用$next
回调$request
。
最好将中间件设想为一系列HTTP请求必须经过“层”才能到达您的应用程序。每一层都可以检查请求,甚至完全拒绝它。
中间件之前 / 之后
中间件在请求之前还是之后运行取决于中间件本身。例如,以下中间件将在应用程序处理请求之前执行某些任务:
<?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()
方法的调用中列出中间件类:
<?php
$app->middleware([
App\Http\Middleware\OldMiddleware::class
]);
将中间件分配给路由
如果要将中间件分配给特定的路由,则应首先在bootstrap/app.php
文件对$app->routeMiddleware()
方法的调用中为中间件分配一个快捷键:
$app->routeMiddleware([
'auth' => App\Http\Middleware\Authenticate::class,
]);
在HTTP内核中定义了中间件后,您可以middleware
在route options数组中使用密钥:
$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) {
//
}]);
终止中间件
有时,在HTTP响应已发送到浏览器之后,中间件可能需要做一些工作。例如,在将响应发送到浏览器之后,“会话”中间件将会话数据写入存储。为此,通过向中间件添加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
方法应同时接收请求和响应。定义了可终止的中间件后,应将其添加到文件中的全局中间件列表中。bootstrap/app.php
在terminate
中间件上调用该方法时,Lumen将从服务容器解析中间件的新实例。如果要在调用handle
和terminate
方法时使用相同的中间件实例,请使用容器的singleton
方法在容器中注册中间件。