Maison  >  Article  >  cadre php  >  Une brève analyse des principes de Laravel Auth

Une brève analyse des principes de Laravel Auth

藏色散人
藏色散人avant
2020-08-07 16:01:024175parcourir

Ce qui suit est une brève analyse des principes de Laravel Auth de la colonne du didacticiel Laravel. J'espère que cela sera utile aux amis dans le besoin !

Une brève analyse des principes de Laravel Auth

Depuis que l'entreprise a récemment utilisé Laravel-admin comme backend et est entrée en contact avec le framework Laravel, je dois dire que le pouvoir de la communauté Laravel et de l'écologie est en effet assez fort.

Cependant, les activités internes de l'entreprise sont entièrement du côté Java, et tout le backend ajuste JavaApi, donc les fonctionnalités d'utilisation de Laravel doivent être considérablement réduites. Tout d'abord, le modèle Eloquent ne peut pas être utilisé. tout. Je sépare les affaires ici et je sauvegarde seulement. Il y a 3 tables, qui sont les tables fournies avec Laravel-admin.

Une brève analyse des principes de Laravel Auth

Laravel-admin est livré avec 9 tables Étant donné que les informations de connexion des utilisateurs sont toutes stockées du côté de l'API, j'ai abandonné la fonction de table intégrée. Par conséquent, vous devez implémenter vous-même la logique de connexion Api et vous devez utiliser l'authentification Laravel Auth.

Interprétation des principes

// 使用下面这个命令Laravel会自动为我们生成Auth路由和认证模块。跟着代码往下解读。
  php artisan make:auth 
  
// Http/Controllers/Auth/LoginController 使用了 AuthenticatesUsers

Parmi elles, les trois méthodes suivantes expliquent toute la logique de connexion.

public function login(Request $request)
    {
        $this->validateLogin($request);
        if ($this->hasTooManyLoginAttempts($request)) {
            $this->fireLockoutEvent($request);
            return $this->sendLockoutResponse($request);
        }
        // 这里尝试登录系统,
        if ($this->attemptLogin($request)) {
            return $this->sendLoginResponse($request);
        }
        $this->incrementLoginAttempts($request);
        return $this->sendFailedLoginResponse($request);
    }
    protected function attemptLogin(Request $request)
    {
        return $this->guard()->attempt(
            $this->credentials($request), $request->has('remember')
        );
    }
    protected function guard()
    {
        return Auth::guard();
    }

Le contrôleur recherchera Auth::guard(), alors c'est quoi Auth::guard()

Tout d'abord, Auth est le singleton du système, et le le prototype est en

Illuminate\Auth\AuthManager;

Comme son nom l'indique, il s'agit d'un module de gestion d'authentification qui implémente l'interface d'authentification en mode usine guards(),

public function __construct($app)
    {
        $this->app = $app;
        $this->userResolver = function ($guard = null) {
            return $this->guard($guard)->user();
        };
    }
    // Auth::guard();就是调用了这个方法。
    public function guard($name = null)
    {
        // 首先查找$name, 没有就使用默认的驱动,
        $name = $name ?: $this->getDefaultDriver();
        // 意思就是要实例化出这个驱动并且返回,
        return isset($this->guards[$name])
                    ? $this->guards[$name]
                    : $this->guards[$name] = $this->resolve($name);
    }
   
    // 默认的驱动是从配置文件里面读取的,/config/auth.php default配置项
    public function getDefaultDriver()
    {
        return $this->app['config']['auth.defaults.guard'];
    }
  
   // 这里是构造Auth-guard驱动
   protected function resolve($name)
    {
        $config = $this->getConfig($name);
        if (is_null($config)) {
            throw new InvalidArgumentException("xxx");
        }
        // 这里是如果你自己实现的驱动就返回
        if (isset($this->customCreators[$config['driver']])) {
            return $this->callCustomCreator($name, $config);
        }
        // 这里是系统默认两个类分别是 
       // session 和 token 这里主要讲 sessionGuard .
        $driverMethod = 'create'.ucfirst($config['driver']).'Driver';
        if (method_exists($this, $driverMethod)) {
            return $this->{$driverMethod}($name, $config);
        }
        throw new InvalidArgumentException("xxx");
    }

Jetons un œil au fichier de configuration auth.php

 // Auth::guard() ,不传参数,就调用默认的default.guard ,
   'defaults' => [
        'guard' => 'web',
        'passwords' => 'users',
    ],
   // 系统的guard .默认支持 "database", "eloquent",意思就是说你的provider必须是这两个实例中的一个,
    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
        'api' => [
            'driver' => 'token',
            'provider' => 'users',
        ],
    ],
  // 这个就是上面的provider了,你使用哪一个provider作为你的Auth::guard()返回的
 // 模型
    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\User::class,
        ],
        // 'users' => [
        //     'driver' => 'database',
        //     'table' => 'users',
        // ],
    ],

En d'autres termes, après tout, Auth::guard(), dans la configuration par défaut, me renvoie un sessionGuard

Regardez principalement les quatre méthodes suivantes

.
namespace Illuminate\Auth;
class SessionGuard{
    public function attempt(array $credentials = [], $remember = false)
    {
        // 这里触发 试图登录事件,此时还没有登录
        $this->fireAttemptEvent($credentials, $remember);
        $this->lastAttempted = 
        $user = $this->provider->retrieveByCredentials($credentials);
        // 这里会调用hasValidCredentials,其实就是验证用户名和密码的一个过程
        if ($this->hasValidCredentials($user, $credentials)) {
            // 如果验证通过了,就调用login方法 .
            $this->login($user, $remember);
            return true;
        }
        // 否则就触发登录失败事件,返回假
        $this->fireFailedEvent($user, $credentials);
        return false;
    }
    // 这里是登录用户的操作,就是说调用这个方法已经是合法用户了,必须是一个
  // AuthenticatableContract 的实例 .
    public function login(AuthenticatableContract $user, 
    $remember = false)
    {
        // 直接更新session,这里就是把session存起来,session的键在该方法的
        // getName() 里边,
        $this->updateSession($user->getAuthIdentifier());
        if ($remember) {
            $this->ensureRememberTokenIsSet($user);
            $this->queueRecallerCookie($user);
        }
     // 触发登录事件,已经登录了这个时候,
        $this->fireLoginEvent($user, $remember);
        // 将user对象保存到sessionGuard , 后续的类访问Auth::user();直接拿到
        $this->setUser($user);
    }
    // 这里就是经常使用到的 Auth::user()了,具体如何返回看AuthManager里面的
    // __call
    public function user()
    {
        if ($this->loggedOut) {
            return;
        }
        if (! is_null($this->user)) {
            return $this->user;
        }
        // 这里读取session拿到user的id ,
        $id = $this->session->get($this->getName());
        $user = null;
        // 如果拿到了id ,查找到该user
        if (! is_null($id)) {
            if ($user = $this->provider->retrieveById($id)) {
                $this->fireAuthenticatedEvent($user);
            }
        }
        $recaller = $this->recaller();
        if (is_null($user) && ! is_null($recaller)) {
            $user = $this->userFromRecaller($recaller);
            if ($user) {
                $this->updateSession($user->getAuthIdentifier());
                $this->fireLoginEvent($user, true);
            }
        }
        return $this->user = $user;
    }
    // 这里就直接返回用户id了,
    public function id()
    {
        if ($this->loggedOut) {
            return;
        }
        return $this->user()
                    ? $this->user()->getAuthIdentifier()
                    : $this->session->get($this->getName());
    }
}

De manière générale, le processus de connexion de l'utilisateur est terminé. Le processus simple consiste à

//伪代码
$credentials = $request()->only(['username' ,'password']);
if(Auth::guard("session")->attempt($credentials)){
  // 登录成功
}else{
  // 登录失败
}

implémenter un contrôleur/une méthode accessible uniquement après la connexion de l'utilisateur

Route::get("/home")->middleware("auth");
// auth Middleware 是在app/Http/Kernel中注册的,
// 类名是  \Illuminate\Auth\Middleware\Authenticate::class
// 解析过程实质上是这个方法:
    public function handle($request, Closure $next, ...$guards)
    {
        $this->authenticate($guards);
        return $next($request);
    }
  
    protected function authenticate(array $guards)
    {  
        // 默认情况下会去 Auth中寻找authenticate这个方法
        if (empty($guards)) {
            return $this->auth->authenticate();
        }
        // 如果middleware中传了参数,会遍历一遍,不通过就抛出异常
        foreach ($guards as $guard) {
            if ($this->auth->guard($guard)->check()) {
                return $this->auth->shouldUse($guard);
            }
        }
        throw new AuthenticationException('Unauthenticated.', $guards);
    }
    //sessionGuard 中的authenticate其实也就是调用了一遍user方法。
    public function authenticate()
    {
        if (! is_null($user = $this->user())) {
            return $user;
        }
        throw new AuthenticationException;
    }

C'est mon c'est la première fois que j'écris un article. S'il y a des erreurs, merci de les signaler.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer