HTTP 中间件
HTTP 中间件
介绍
HTTP 中间件提供一个方便的机制来过滤访问应用的请求,例如 Lumen 使用 Auth
中间件来验证用户的合法性,如果用户没有通过验证,该中间件会将用户重定向到登录页。反之, 中间件允许请求并进一步执行。
当然,除了身份验证,中间件还可以用来执行各种任务。 例如:CORS 中间件给所有返回的请求加上正确的头部,日志中间件会记录所有进入应用的请求。
所有的中间件都应放在 app/Http/Middleware
目录下。
创建中间件
为了正确的创建中间件,我们先复制 Lumen 自带的中间件示例 ExampleMiddleware
文件。在这个示例中,我们只允许参数 age
大于 200 时才能访问下一步,否则,会将用户重定向到 「home」这个表示首页的页面上。(PS:有点拦路求财的意思)
<?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 请求必须到达应用之前必须经过这些 “关卡” 。每一个 “关卡” 可以对请求进行检查,甚至可以完全拒绝请求。
前置 & 后置 中间件
中间件是在请求之前或之后执行取决于中间件本身。例如,下面的这个中间件将在应用处理请求 之前 执行一些任务:
<?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,
]);
添加好中间件之后, 你可以在路由中添加以 middleware
为键名,值为设定好的$app
:
$router->get('admin/profile', ['middleware' => 'auth', function () {
//
}]);
在路由中使用多个中间件:
$router->get('/', ['middleware' => ['first', 'second'], function () {
//
}]);
多个路由使用同一个中间件:
$router->group(['middleware' => 'test'], function($router){
$router->get('login', 'LoginController@login');
$router->get('test', 'TestController@test');
});
中间件参数
中间件可以接收自定义参数。举个栗子?,如果你的应用程序需要校验某个用户角色是否具有某个操作的权限,你可以创建一个 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 」中间件存储 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
方法必须同时接受请求和响应。一旦定义了 terminable 中间件,就应该把它添加到 bootstrap/app.php
文件中的全局中间件清单中。
当在中间件中调用 terminate
方法时,Lumen 将会从 服务容器 中解析一个全新的中间件实例。如果想在 handle
和 terminate
方法被调用时使用一致的中间件实例,只需在容器中使用容器的 singleton
方法注册中间件。
本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。