1. 註冊認證中間件, 在文件 app/Http/Kernel.php 內完成:
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,
'checkuid' => \App\Http\Middleware\CheckUid::class,
];
2. 認證中間件的源碼文件:vendor/laravel/framework/src/Illuminate/Auth/Middleware/Authenticate.php 。其中:
use Illuminate\Contracts\Auth\Factory as Auth;
public function __construct(Auth $auth)
{
$this->auth = $auth; //Auth 工廠類,這裏注入的是 Illuminate\Auth\AuthManager
}
public function handle($request, Closure $next, ...$guards)
{
$this->authenticate($guards);
return $next($request);
}
protected function authenticate(array $guards)
{
if (empty($guards)) {
//若是沒有指定guard 則使用默認
return $this->auth->authenticate(); //經過Illuminate\Auth\AuthManager\__call() 調用 建立guard 實例,並調用guard 實例的 authenticate() 方法進行認證
}
foreach ($guards as $guard) {
if (
$this->auth->guard($guard)->check()) {//使用指定的guard中第一個能成功認證的
return $this->auth->shouldUse($guard);
//將指定guard設置爲 本次請求的默認guard。(本次請求後續獲取authed user時,都經過這裏設置的guard進行)
}
}
throw new AuthenticationException('Unauthenticated.', $guards);
}
2.1
$this->auth->authenticate(); //進行身份認證
文件: vendor/laravel/framework/src/Illuminate/Auth/AuthManager.php
public function __call($method, $parameters)
{
return
$this->guard()->{$method}(...$parameters);
}
2.2
$this->guard() //獲取guard實例
文件: vendor/laravel/framework/src/Illuminate/Auth/AuthManager.php
public function guard($name = null)
{
$name = $name ?:
$this->getDefaultDriver();
return isset($this->guards[$name])
? $this->guards[$name] //單例
: $this->guards[$name] =
$this->resolve($name); //獲取 guard 實例
}
public function getDefaultDriver()
{
return $this->app['config']['auth.defaults.guard'];
//從配置文件內讀取默認guard
}
protected function resolve($name)
{
$config = $this->getConfig($name);
//獲取指定guard配置信息
if (is_null($config)) {
throw new InvalidArgumentException("Auth guard [{$name}] is not defined.");
}
if (isset($this->customCreators[$config['driver']])) {
//若是設置了自定義工廠,則使用之
return $this->callCustomCreator($name, $config);
}
//相似 createSessionDriver, createTokenDriver 等格式
$driverMethod = 'create'.ucfirst($config['driver']).'Driver';
if (method_exists($this, $driverMethod)) {
return $this->{$driverMethod}($name, $config);
}
throw new InvalidArgumentException("Auth guard driver [{$name}] is not defined.");
}
public function createSessionDriver($name, $config)
{
$provider = $this->createUserProvider($config['provider']);
$guard = new SessionGuard($name, $provider, $this->app['session.store']);
// When using the remember me functionality of the authentication services we
// will need to be set the encryption instance of the guard, which allows
// secure, encrypted cookie values to get generated for those cookies.
if (method_exists($guard, 'setCookieJar')) {
$guard->setCookieJar($this->app['cookie']);
}
if (method_exists($guard, 'setDispatcher')) {
$guard->setDispatcher($this->app['events']);
}
if (method_exists($guard, 'setRequest')) {
$guard->setRequest($this->app->refresh('request', $guard, 'setRequest'));
}
return $guard;
}
2.3
$this->guard()->authenticate() //使用獲取的 guard 實例進行身份認證
文件: vendor/laravel/framework/src/Illuminate/Auth/SessionGuard.php
類中 use 了 GuardHelpers trait
文件:vendor/laravel/framework/src/Illuminate/Auth/GuardHelpers.php
public function authenticate()
{
if (! is_null(
$user = $this->user())) {
return $user;
}
throw new AuthenticationException;
}
文件: vendor/laravel/framework/src/Illuminate/Auth/SessionGuard.php
//此方法是真正進行身份認證的地方!!!!
public function user()
{
if ($this->loggedOut) {
return;
}
// If we've already retrieved the user for the current request we can just
// return it back immediately. We do not want to fetch the user data on
// every call to this method because that would be tremendously slow.
if (! is_null($this->user)) {
return $this->user;
}
$id = $this->session->get($this->getName());
//從session中獲取用戶ID。已登陸用戶的用戶ID會被存儲在Session內。
// First we will try to load the user using the identifier in the session if
// one exists. Otherwise we will check for a "remember me" cookie in this
// request, and if one exists, attempt to retrieve the user using that.
$user = null;
if (! is_null($id)) {
if ($user = $this->provider->retrieveById($id)) {
//經過Illuminate\Auth\EloquentUserProvider 的retrieveById() 方法,獲取用戶信息,並返回User Model
$this->fireAuthenticatedEvent($user);
}
}
// If the user is null, but we decrypt a "recaller" cookie we can attempt to
// pull the user data on that cookie which serves as a remember cookie on
// the application. Once we have a user we can return it to the caller.
$recaller = $this->getRecaller();
//獲取認證cookie(登陸時選中記住我,服務端會向瀏覽器設置一個認證cookie,其中包括 remember_token,下次能夠直接使用這個認證cookie進行登陸)
if (is_null($user) && ! is_null($recaller)) {
$user = $this->getUserByRecaller($recaller);
//使用 remember_token 從數據庫中獲取用戶信息 (最終是委託 Illuminate\Auth\EloquentUserProvider::retrieveByToken() 方法來取數據)
if ($user) {
$this->updateSession($user->getAuthIdentifier()); //將用戶ID保存到Session
$this->fireLoginEvent($user, true);
}
}
return $this->user = $user;
}