中间件提供了一种方便的机制来过滤进入应用程序的HTTP请求。
例如,Laravel包含一个中间件,用于验证应用程序的用户是否经过身份验证。如果用户未经过身份验证,则中间件会将用户重定向到登录屏幕。但是,如果用户已通过身份验证,则中间件将允许请求继续进入应用程序。
当然,除了身份验证之外,还可以编写其他中间件来执行各种任务。CORS中间件可能负责为离开您的应用程序的所有响应添加正确的标头。记录中间件可能会将所有传入请求记录到您的应用程序中。
Laravel框架中包含多个中间件,包括用于身份验证和CSRF保护的中间件。所有这些中间件都位于目录中。app/Http/Middleware
要创建新的中间件,请使用Artisan命令:make:middleware
注册中间件
全球中间件
如果您希望在对应用程序的每个HTTP请求期间运行中间件,请在类的$middleware
属性中列出中间件类。app/Http/Kernel.php
将中间件分配给路由
如果要将中间件分配给特定路由,则应首先为中间件分配文件中的密钥。默认情况下,此类的属性包含Laravel附带的中间件的条目。要添加自己的,请将其附加到此列表并为其指定一个您选择的键。例如:app/Http/Kernel.php
$routeMiddleware
/** * The application's route middleware. * * These middleware may be assigned to groups or used individually. * * @var array */ protected $routeMiddleware = [ 'auth' => \Illuminate\Auth\Middleware\Authenticate::class, 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, 'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class, 'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class, 'can' => \Illuminate\Auth\Middleware\Authorize::class, 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, 'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class, 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, //'auth' => \App\Http\Middleware\Authenticate::class, 'permission' => \App\Http\Middleware\Permission::class, ];
一旦在HTTP内核中定义了中间件,您就可以使用该middleware
方法将中间件分配给路由:
Route::get('admin/profile', function () {
//
})->middleware('auth');
您还可以为路径分配多个中间件:
Route::get('/', function () {
//
})->middleware('first', 'second');
分配中间件时,您还可以传递完全限定的类名:
use App\Http\Middleware\CheckAge;
Route::get('admin/profile', function () {
//
})->middleware(CheckAge::class);
中间件组
有时您可能希望将一个中间件组合在一个密钥下,以便更容易地分配给路由。您可以使用$middlewareGroups
HTTP内核的属性执行此操作。
开箱即用,Laravel自带web
并api
包含您可能要应用到您的Web用户界面和API路线常见中间件中间件组:
/** * The application's route middleware groups. * * @var array */ protected $middlewareGroups = [ 'web' => [ \App\Http\Middleware\EncryptCookies::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, \App\Http\Middleware\VerifyCsrfToken::class, \Illuminate\Routing\Middleware\SubstituteBindings::class, ], 'api' => [ 'throttle:60,1', 'bindings', \App\Http\Middleware\LogRequest::class ], ];
可以使用与单个中间件相同的语法将中间件组分配给路由和控制器动作。同样,中间件组可以更方便地同时为路径分配许多中间件:
Route::get('/', function () {
//
})->middleware('web');
Route::group(['middleware' => ['web']], function () {
//
});
开箱即用,web
中间件组将自动应用于您的文件。routes/web.php
RouteServiceProvider
中间件还可以接收其他参数。例如,如果您的应用程序需要在执行给定操作之前验证经过身份验证的用户是否具有给定的“角色”,则可以创建一个CheckRole
接收角色名称作为附加参数的中间件。
其他中间件参数将在$next
参数后传递给中间件:
<?php
namespace App\Http\Middleware;
use Closure;
class CheckRole
{
/**
* Handle the incoming request.
*
* @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);
}
}
通过将中间件名称和参数与a分开来定义路径时,可以指定中间件参数:
。多个参数应以逗号分隔:
Route::put('post/{id}', function ($id) {
//
})->middleware('role:editor');
可终止的中间件
在将HTTP响应发送到浏览器之后,有时中间件可能需要做一些工作。例如,Laravel附带的“会话”中间件在将响应发送到浏览器后将会话数据写入存储。如果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
方法应同时接收请求和响应。一旦定义了可终止的中间件,就应该将其添加到文件中的路由或全局中间件列表中。app/Http/Kernel.php
在terminate
中间件上调用方法时,Laravel将从服务容器中解析新的中间件实例。如果您想在调用handle
和terminate
方法时使用相同的中间件实例,请使用容器的singleton
方法向容器注册中间件。