HTTP中间件
学院君创立于5年前,最后更新于11个月前
版本号#2
51498视图
40 likes
0咨询
1、个人资料
HTTP中间件为过滤进入APP应用程序的HTTP请求提供了便利的机制。 例如,Laravel具有内置的中间件,用于验证用户是否得到授权,如果用户没有得到授权,则中间件会将用户重定向到登录页面。 否则,如果用户得到批准,中间件将允许请求进入下一步。
当然,中间件不仅可以用于身份验证,还可以用于处理更多的任务。 例如,CORS中间件可用于向离开站点的响应添加适当的标头(跨域)。 日志中间件可以记录访问站点的所有请求。
Laravel框架附带中间件,如维护模式、认证和CSRF保护中间件。 的所有中间件都位于app/Http/Middleware目录中。
2、定义中间件
要创建新中间件,请使用Artisan命令make:middleware。
phpartisanmake : middlewareoldmiddleware
此命令在app/Http/Middleware目录下创建新的中间件类OldMiddleware。 此中间件只允许提供的age大于200的访问路由。 否则,将用户重定向到主页。
名称空间apphttpmiddleware;
用户关闭;
class OldMiddleware
{
//*
*返回请求筛选器
*
* @ paramilluminatehttprequest $ request
* @param Closure $next
* @return mixed
*/
公共函数手持机($ request,Closure $next )
{
if($request-input('age ) )。
返回重定向(' home );
}
返回$ next ($ request;
}
}
如您所见,如果age=200,中间件将返回HTTP并重定向到客户端,否则请求将被传递。 可以调用回调函数$next将请求传递给$request。
了解中间件的最好方法是将其视为HTTP请求在到达目标操作之前必须通过的“层”。 每个层都可以检查请求并完全拒绝。
中间件之前/之后
一个中间件是否在请求前或请求后运行取决于中间件本身。 例如,以下中间件在处理请求之前执行一些任务:
名称空间apphttpmiddleware;
用户关闭;
类before中间件
{
公共函数手持机($ request,Closure $next )
{
//采取行动
返回$ next ($ request;
}
}
但是,以下中间件在请求处理后执行任务。
名称空间apphttpmiddleware;
用户关闭;
class AfterMiddleware
{
公共函数手持机($ request,Closure $next )
{
$response=$next($request;
//采取行动
返回$响应;
}
}
3、注册中间件
全局中间件
要确保中间件在每个HTTP请求之间运行,只需将相应的中间件类设置为app/Http/Kernel.php的数组属性$middleware。
将中间件分配给路由
如果要将中间件分配给指定的根,必须首先在app/Http/Kernel.php文件中将其分配给简单的key。 缺省情况下,此类的$routeMiddleware属性包含Laravel内置的门户中间件。 要添加自己的中间件,只需将其添加到后面并分配密钥即可。
在AppHttpKernel中
保护性$ route middleware=[
' auth '=apphttpmiddlewareauthenticate 3360:类,
' auth.basic '
=> IlluminateAuthMiddlewareAuthenticateWithBasicAuth::class,'guest' => AppHttpMiddlewareRedirectIfAuthenticated::class,
'throttle' => IlluminateRoutingMiddlewareThrottleRequests::class,
];
中间件在 HTTP Kernel 中被定义后,可以在路由选项数组中使用 $middleware 键来指定该中间件:
Route::get('admin/profile', ['middleware' => 'auth', function () {
//
}]);
使用数组分配多个中间件到路由:
Route::get('/', ['middleware' => ['first', 'second'], function () {
//
}]);
除了使用数组外,还可以使用 middleware 方法链的方式定义路由:
Route::get('/', function () {
//
})->middleware(['first', 'second']);
中间件组
有时候你可能想要通过指定一个键名的方式将相关中间件分到一个组里面,从而更方便将其分配到路由中,这可以通过使用 HTTP Kernel 的 $middlewareGroups 实现。
Laravel 自带了开箱即用的 web 和 api 两个中间件组以包含可以应用到 Web UI 和 API 路由的通用中间件:
/**
* 应用的路由中间件组
*
* @var array
*/
protected $middlewareGroups = [
'web' => [
AppHttpMiddlewareEncryptCookies::class,
IlluminateCookieMiddlewareAddQueuedCookiesToResponse::class,
IlluminateSessionMiddlewareStartSession::class,
IlluminateViewMiddlewareShareErrorsFromSession::class,
AppHttpMiddlewareVerifyCsrfToken::class,
],
'api' => [
'throttle:60,1',
'auth:api',
],
];
中间件组可以被分配给路由和控制器动作,使用和单个中间件分配同样的语法。再次申明,中间件组的目的只是让一次分配给路由多个中间件的实现更加简单:
Route::group(['middleware' => ['web']], function () {
//
});
4、中间件参数
中间件还可以接收额外的自定义参数,例如,如果应用需要在执行给定动作之前验证认证用户是否拥有指定的角色,可以创建一个 RoleMiddleware 来接收角色名作为额外参数。
额外的中间件参数会在 $next 参数之后传入中间件:
namespace AppHttpMiddleware;
use Closure;
class RoleMiddleware
{
/**
* 运行请求过滤器
*
* @param IlluminateHttpRequest $request
* @param Closure $next
* @param string $role
* @return mixed
* translator https://xueyuanjun.com
*/
public function handle($request, Closure $next, $role)
{
if (! $request->user()->hasRole($role)) {
// Redirect...
}
return $next($request);
}
}
中间件参数可以在定义路由时通过:分隔中间件名和参数名来指定,多个中间件参数可以通过逗号分隔:
Route::put('post/{id}', ['middleware' => 'role:editor', function ($id) {
//
}]);
5、终端中间件
有时候中间件可能需要在 HTTP 响应发送到浏览器之后做一些工作。比如,Laravel 内置的“session”中间件会在响应发送到浏览器之后将 Session 数据写到存储器中,为了实现这个,定义一个可终止的中间件并添加 terminate 方法到这个中间件:
namespace IlluminateSessionMiddleware;
use Closure;
class StartSession
{
public function handle($request, Closure $next)
{
return $next($request);
}
public function terminate($request, $response)
{
// 存储session数据...
}
}
terminate 方法将会接收请求和响应作为参数。一旦你定义了一个可终止的中间件,应该将其加入到 HTTP kernel 的全局中间件列表中。
当调用中间件上的 terminate 方法时,Laravel 将会从服务容器中取出该中间件的新的实例,如果你想要在调用 handle 和 terminate 方法时使用同一个中间件实例,则需要使用容器的 singleton 方法将该中间件注册到容器中。