zoukankan      html  css  js  c++  java
  • laravel5.8 Auth::guide

    // 使用下面这个命令Laravel会自动为我们生成Auth路由和认证模块。跟着代码往下解读。
      php artisan make:auth 
      
    // Http/Controllers/Auth/LoginController 使用了 AuthenticatesUsers 
    
    其中 下面这三个方法诠释了登录逻辑的全部。
    
        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();
        }
    

    控制器会去寻找Auth::guard(), 那这个Auth::guard()是个什么东西呢,

    首先 Auth 是系统的单例,原型在

    IlluminateAuthAuthManager;
    

    顾名思义,是一个Auth管理模块,实现了认证工厂模式接口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");
        }
    

    接下来看看配置文件 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' => AppUser::class,
            ],
    
            // 'users' => [
            //     'driver' => 'database',
            //     'table' => 'users',
            // ],
        ],
    

    也就是说终归到底,Auth::guard(), 在默认配置里面是给我反回了一个sessionGuard .

    主要看下面4个方法

    namespace IlluminateAuth;
    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());
        }
    }
    

    大体上用户登录的流程就完了,简单过程就是

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

    实现用户登录之后才能访问的控制器/方法

    Route::get("/home")->middleware("auth");
    
    // auth Middleware 是在app/Http/Kernel中注册的,
    // 类名是  IlluminateAuthMiddlewareAuthenticate::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;
        }


    原文链接:https://juejin.im/entry/5959f64e6fb9a06bb4747c41
  • 相关阅读:
    SVN中Revert changes from this revision 跟Revert to this revision
    bootstrap中如何使input中的小图标获得点击事件
    基于Bootstrap使用jQuery实现输入框组input-group的添加与删除-改进版
    MVC4 Controller 与 WebApi 的 Session 传值问
    MVC Razor与javascript混编(js中嵌入razor)
    Asp.net mvc怎么在razor里写js代码
    MVC后台数据赋值给前端JS对象
    ASP.NET MVC自定义验证Authorize Attribute(包含cookie helper)
    ASP.Net MVC4+Memcached+CodeFirst实现分布式缓存
    【记录】【solr】solr7.2.1原子更新
  • 原文地址:https://www.cnblogs.com/cbugs/p/11248088.html
Copyright © 2011-2022 走看看