Laravel从入门到上线运营-08中间件篇
上次我们简单的做了一下登录注册,我们使用了框架里写好的登录方法 auth()->login($user)
。
简单的解释一下登录原理,执行这个登录方法会在你的浏览器里保存一个 cookie
。当你访问这个网站的时候,会自动读取 cookie
,如果有用户信息的 cookie
存在,就会拿这个数据去数据库里查询
cookie
没有过期或者其他问题的话,就是每次访问网页,就会都去查询一次用户表,用户存在即代表该用户为登录状态。所以同一个设备下使用不同浏览器,或者使用 chrome
的无痕模式,是不同登录状态。
我们做一个验证,访问 b/login
,登录一个账号,再在 Providers/AppServiceProvider.php
文件里添加数据库查询记录监听
<?php
namespace App\Providers;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Str;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
//
}
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
//sql日志记录
DB::listen(function ($q) {
info(Str::replaceArray('?', $q->bindings, $q->sql). ' '. $q->time. 'ms'); //info 日志是记录
});
}
}
请求一次网页,在 storage/logs
的今天日志文件里就会多一段记录。
[2019-10-11 13:01:29] local.INFO: select * from `users` where `id` = 1 limit 1 73.17ms
讲完登录我们再讲一下 csrf
,我们昨天讲到除了 get
以外的请求,都需要通过 csrf
验证。那每次请求就是通过 csrf
的中间件的方式去验证的。中间件文件放在 app/Http/Middleware
目录下。
其中的 VerifyCsrfToken.php
就是 csrf
中间件。那一个请求具体经过哪些中间件是在 blog/app/Http/Kernel.php
中配置。
protected $middleware = [
\App\Http\Middleware\TrustProxies::class,
\App\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];
第一个数组就是所有请求都会经过的中间件。我们直接把最后一个注释掉,它的作用是把请求参数中的空字符串转为 null
,没什么用。
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',
],
];
第二个数组是根据不同的请求方式经过不同的中间件,就两种 web
网页请求,api
接口请求。
protected $routeMiddleware = [
'auth' => \App\Http\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,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
];
第三个数组是对中间件命名,名字会在路由中用到。
protected $middlewarePriority = [
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\Authenticate::class,
\Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\Illuminate\Auth\Middleware\Authorize::class,
];
第四个数组是规定中间件的执行顺序。
现在我们自己来建一个中间件,用来记录每次的请求。使用命令行创建
php artisan make:middleware RequestInfo
<?php
namespace App\Http\Middleware;
use Closure;
class RequestInfo
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
//请求记录
info("\r\r=============================================================\r
[url]: " . $request->ip() . "\r" . $request->url() . " " . $request->getMethod() . "\r\r
[Authorization]:\r" . $request->header('Authorization') . "\r\r
[body]:\r" . json_encode($request->all(), true) . "\r");
return $next($request);
}
}
在 app/Http/Kernel.php
第一个数组中加入它
protected $middleware = [
\App\Http\Middleware\TrustProxies::class,
\App\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\App\Http\Middleware\RequestInfo::class,
// \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];
这时候我们访问网页就会有详细的信息记录下来,开发的时候可以看看自己到底传了什么参数过来。
我们再来试试在路由上添加中间件,假设我们网站的首页是需要登录,框架已经帮我们写好了一个登录验证中间件,修改路由文件。
Route::get('/', 'IndexController@index')->middleware('auth'); // 给该路由添加 auth 中间件
Route::get('register', 'RegisterController@index');
Route::post('register', 'RegisterController@register');
Route::get('login', 'LoginController@index')->name('login'); //name 方法是对路由进行命名,个人觉得路由地址本身就是名字了,再起名字似乎多余了
Route::post('login', 'LoginController@login');
打开 chrome
里的无痕模式,访问 b/
。就会发现被自动转到了登录界面,这就是 'auth' => \App\Http\Middleware\Authenticate::class,
该中间件启的作用。
还可以在 controller
中的 __construct
对方法进行中间件设置。
public function __construct()
{
$this->middleware('auth')->only('index');
}
中间件的其他部分,同学们自行学习。