zoukankan      html  css  js  c++  java
  • Laravel 5.3 auth中间件底层实现详解(转)

    1. 注册认证中间件, 在文件 app/Http/Kernel.php 内完成:

    protected $routeMiddleware = [
        'auth' => IlluminateAuthMiddlewareAuthenticate::class,
        'auth.basic' => IlluminateAuthMiddlewareAuthenticateWithBasicAuth::class,
        'bindings' => IlluminateRoutingMiddlewareSubstituteBindings::class,
        'can' => IlluminateAuthMiddlewareAuthorize::class,
        'guest' => AppHttpMiddlewareRedirectIfAuthenticated::class,
        'throttle' => IlluminateRoutingMiddlewareThrottleRequests::class,
        'checkuid' => AppHttpMiddlewareCheckUid::class,
    ];


    2. 认证中间件的源码
    文件:vendor/laravel/framework/src/Illuminate/Auth/Middleware/Authenticate.php 。其中:

    use IlluminateContractsAuthFactory as Auth;
    public function __construct(Auth $auth)
    {
        $this->auth = $auth; //Auth 工厂类,这里注入的是 IlluminateAuthAuthManager
    }
    
    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(); //通过IlluminateAuthAuthManager\__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)) { //通过IlluminateAuthEloquentUserProvider 的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 从数据库中获取用户信息 (最终是委托 IlluminateAuthEloquentUserProvider::retrieveByToken() 方法来取数据)
             
            if ($user) {
                $this->updateSession($user->getAuthIdentifier()); //将用户ID保存到Session
                $this->fireLoginEvent($user, true);
            }
        }
         
        return $this->user = $user;
    }


    原文地址:http://www.cnblogs.com/tao100/p/6073542.html

  • 相关阅读:
    POJ 3114 Tarjan+Dijkstra
    278. First Bad Version
    209. Minimum Size Subarray Sum
    154. Find Minimum in Rotated Sorted Array II
    153. Find Minimum in Rotated Sorted Array
    710. Random Pick with Blacklist
    767. Reorganize String
    524. Longest Word in Dictionary through Deleting
    349. Intersection of Two Arrays
    350. Intersection of Two Arrays II
  • 原文地址:https://www.cnblogs.com/chy1000/p/7484962.html
Copyright © 2011-2022 走看看