[Laravel 5.5 document] Filter for user request--http request: Middleware
Http://laravelacademy.org/post/7812.html
Brief introduction
Middleware provides a convenient mechanism for filtering HTTP requests that enter the application. For example, Laravel has a built-in middleware to verify whether a user is authenticated (such as a login), and if the user is not certified, the middleware redirects the user to the login page, and if the user is already authenticated, the middleware will allow the request to proceed to the next step.
Of course, in addition to authentication, middleware can also be used to handle many other tasks. For example, CORS middleware can be used to add the appropriate header (cross-domain) for the response to leave the site, and the log middleware can log all requests for entry to the site, thus enabling us to build the system log system.
Laravel framework comes with some middleware, including authentication, CSRF protection middleware and so on. All middleware is located in the app/Http/Middleware
directory.
This tutorial will focus on the definition, registration, and use of middleware.
Defining middleware
To create a new middleware, you can use the Artisan command make:middleware
:
php artisan make:middleware CheckToken
This command app/Http/Middleware
creates a new middleware class in the directory, in which CheckToken
we only allow token
request access routes that are equal to the specified value, laravelacademy.org
otherwise we will jump to the Laravel Academy website:
?
As you can see, if the token != ‘laravelacademy.org‘
middleware returns an HTTP redirect to Laravel College; otherwise, the request will be passed down. Passing the request down can be done by invoking the callback function $next
and passing in the current $request
.
Note: At this time just define the logic of the middleware, in order for this middleware to take effect, but also to register it to the specified route, we will soon in the following registration middleware section to teach you how to do.
The best way to understand middleware is to think of the middleware as a "layer" that the HTTP request must pass before it reaches the target action, and each layer examines the request and can reject it completely.
Middleware before/after request
Whether a middleware is executed before or after a request depends on the middleware itself. For example, the following middleware performs some tasks before the request is processed:
<?phpnamespace App\Http\Middleware;use Closure;class BeforeMiddleware{ public function handle($request, Closure $next) { // 执行动作 return $next($request); }}
The following middleware performs its tasks after the request is processed:
<?phpnamespace App\Http\Middleware;use Closure;class AfterMiddleware{ public function handle($request, Closure $next) { $response = $next($request); // 执行动作 return $response; }}
Register middleware
Middleware is divided into three categories, namely, Global middleware, middleware group and the specified routing middleware:
Global middleware
If the middleware you want to define is executed on every HTTP request, simply add the corresponding middleware class to app/Http/Kernel.php
the array properties $middleware
:
?
But unless we really need to, we will not generally put the business-level middleware into the global middleware.
Assigning middleware to a specified route
If you want to assign middleware to a specified route, you should first assign it to app/Http/Kernel.php
the middleware in the file key
, by default, the class's $routeMiddleware
properties contain the middleware that Laravel comes with, and to add your own middleware, simply append it to the back and assign it a key
For example:
// 在 App\Http\Kernel 类中.../** * 应用的路由中间件列表 * * 这些中间件可以分配给路由组或者单个路由 * * @var array */protected $routeMiddleware = [ ‘auth‘ => \Illuminate\Auth\Middleware\Authenticate::class, ‘auth.basic‘ => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, ‘bindings‘ => \Illuminate\Routing\Middleware\SubstituteBindings::class, ‘can‘ => \Illuminate\Auth\Middleware\Authorize::class, ‘guest‘ => \App\Http\Middleware\RedirectIfAuthenticated::class, ‘throttle‘ => \Illuminate\Routing\Middleware\ThrottleRequests::class, ‘token‘ => CheckToken::class];
Once the middleware is defined in HTTP Kernel, it can be middleware
assigned to a route using the method:
Route::get(‘/‘, function () { //})->middleware(‘token‘);
This way, when we access it in the browser http://blog.dev
, we will jump to it http://laravelacademy.org
, only to see the following effect when we access it http://blog.dev?token=laravelacademy.org
:
?
You can use arrays to assign multiple middleware to routes:
Route::get(‘/‘, function () { //})->middleware(‘token‘, ‘auth‘);
The full class name can also be passed when the middleware is allocated (although this is not recommended):
use App\Http\Middleware\CheckToken;Route::get(‘admin/profile‘, function () { //})->middleware(CheckToken::class);
Middleware Group
Sometimes you might want to distribute the relevant middleware into the same group by specifying a key name, which makes it easier to assign it to a route, which can be implemented by using the properties provided by HTTP Kernel $middlewareGroups
.
Laravel comes with out-of-the-box web
and api
two middleware groups, each containing a common middleware that can be applied to Web and API routing:
/** * 应用的中间件组 * * @var array */protected $middlewareGroups = [ ‘web‘ => [ \App\Http\Middleware\EncryptCookies::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, // \Illuminate\Session\Middleware\AuthenticateSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, \App\Http\Middleware\VerifyCsrfToken::class, \Illuminate\Routing\Middleware\SubstituteBindings::class, ], ‘api‘ => [ ‘throttle:60,1‘, ‘bindings‘, ],];
Middleware groups use and assign a single middleware the same syntax is assigned to Routing and controller actions. Again, the purpose of the middleware group is to make it easier to assign a single assignment to multiple middleware implementations:
Route::get(‘/‘, function () { //})->middleware(‘web‘);Route::group([‘middleware‘ => [‘web‘]], function () { //});
By default, RouteServiceProvider
middleware groups are automatically web
applied to routes/web.php
files, and middleware groups are api
applied to routes/api.php
:
?
Of course, we can set our own middleware groups to achieve a more flexible middleware allocation strategy:
/** * 应用的中间件组. * * @var array */protected $middlewareGroups = [ ‘web‘ => [ \App\Http\Middleware\EncryptCookies::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, // \Illuminate\Session\Middleware\AuthenticateSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, \App\Http\Middleware\VerifyCsrfToken::class, \Illuminate\Routing\Middleware\SubstituteBindings::class, ], ‘api‘ => [ ‘throttle:60,1‘, ‘bindings‘, ], ‘blog‘ => [ ‘token‘, ]];
We modify routes/web.php
the following middleware allocation methods:
Route::group([‘middleware‘=>[‘blog‘]],function(){ Route::get(‘/‘, function () { return view(‘welcome‘, [‘website‘ => ‘Laravel‘]); }); Route::view(‘/view‘, ‘welcome‘, [‘website‘ => ‘Laravel学院‘]);});
This way we http://blog.dev
have http://blog.dev/view
to take parameters when we visit and token=laravelacademy.org
then jump to the Laravel College website.
Middleware parameters
The middleware can also receive additional custom parameters, for example, if the application needs to verify that the authenticated user has the specified role before performing the given action, you can create one CheckRole
to receive the role name as an additional parameter.
Additional middleware parameters are passed into the $next
middleware after the parameters:
<?phpnamespace App\Http\Middleware;use Closure;class CheckRole{ /** * 处理输入请求 * * @param \Illuminate\Http\Request $request * @param \Closure $next * @param string $role * @return mixed * translator http://laravelacademy.org */ public function handle($request, Closure $next, $role) { if (! $request->user()->hasRole($role)) { // Redirect... } return $next($request); }}
The middleware parameters can be :
specified by separating the middleware name and the parameter name when defining the route, and multiple middleware parameters can be separated by commas:
Route::put(‘post/{id}‘, function ($id) { //})->middleware(‘role:editor‘);
Based on the demo example above, this feature is relatively simple to implement and is no longer a standalone demonstration.
Terminal middleware
Terminal middleware can be understood as a back-end processing middleware. Sometimes the middleware may need to do some work after the HTTP response is sent to the browser, for example, Laravel built-in session
middleware will write the Session data to the memory after the response is sent to the browser, in order to achieve this function, you need to define a termination middleware and add terminate
method to this middleware:
<?phpnamespace Illuminate\Session\Middleware;use Closure;class StartSession{ public function handle($request, Closure $next) { return $next($request); } public function terminate($request, $response) { // 存储session数据... }}
terminate
Method will receive requests and responses as parameters. Once you have defined a terminal middleware, you need to add it to app/Http/Kernel.php
the list of global middleware for the file.
When invoking a method on the middleware terminate
, Laravel will take a new instance of the middleware from the service container, and if you want to handle
use the terminate
same middleware instance when calling and the method, you need to use the container- singleton
provided method to register the middleware in a container in a single-case manner. About the service container we'll talk about it later, but not in depth.
[Laravel 5.5 document] Filter for user request--http request: Middleware