迁移yaf项目到laravel5.5,并全面使用passport提供API之自定义加密方式(一)

因为之前的项目是基于yaf的,个人觉得开发相率上laravel 更好,所以迁移到laravel上使用。这就会遇到一个兼容性的问题,比如用户登录就不行,以前加密方式也是自己写的,所以迁移起来,首先就要解决用户登录问题了

laravel 自带的登录

App\Http\Controllers\Auth\LoginController 里面用了一个trait AuthenticatesUsers,主要的登录逻辑在这里:

  • showLoginForm 显示登录界面
  • login 处理登录请求
  • validateLogin 验证登录请求信息
  • attemptLogin 登录(重要)
  • credentials 过滤不需要的请求信息
  • sendLoginResponse 返回成功登录信息
  • authenticated 认证
  • sendFailedLoginResponse 返回登录失败信息
  • username 默认使用登录的字段,(如果你使用的是phone,那么重写这个方法就可以了)
  • logout 退出登录
  • guard获取守卫者

具体的细节就不说了,主要就看attemptLogin

  protected function attemptLogin(Request $request)
    {
        
        return $this->guard()->attempt(
            $this->credentials($request), $request->has('remember')
        );
    }
    
    
   
    protected function guard()
    {
        return Auth::guard();
    }
    

$this->guard()就是获取到Auth:guard(),那么这个facade又是什么呢,看一下这个facade:

   protected static function getFacadeAccessor()
    {
        return 'auth';
    }

那么看一下Illuminate\Foundation\ApplicationregisterCoreContainerAliases(别问我怎么一下找到Application来的,以后有机会说一下facade):

  public function registerCoreContainerAliases()
    {
        foreach ([
            'app'                  => [\Illuminate\Foundation\Application::class, \Illuminate\Contracts\Container\Container::class, \Illuminate\Contracts\Foundation\Application::class,  \Psr\Container\ContainerInterface::class],
            'auth'                 => [\Illuminate\Auth\AuthManager::class, \Illuminate\Contracts\Auth\Factory::class],
            'auth.driver'          => [\Illuminate\Contracts\Auth\Guard::class],
            'blade.compiler'       => [\Illuminate\View\Compilers\BladeCompiler::class],
            'cache'                => [\Illuminate\Cache\CacheManager::class, \Illuminate\Contracts\Cache\Factory::class],
            ....
            //省略

可以看到auth 就是\Illuminate\Contracts\Auth\Factory::class的具体实现类\Illuminate\Auth\AuthManager::class,那么我们就可以找到上文说的guard

 public function guard($name = null)
    {
        $name = $name ?: $this->getDefaultDriver();
        return isset($this->guards[$name])
                    ? $this->guards[$name]
                    : $this->guards[$name] = $this->resolve($name);
    }
    
    
     public function getDefaultDriver()
    {
        return $this->app['config']['auth.defaults.guard'];
    }

这里就看到了,默认是configauth.php的配置项web:

 'defaults' => [
        'guard' => 'web',
        'passwords' => 'users',
    ],

接着看$this->resolve('web')是返回了什么鬼:

  protected function resolve($name)
    {
 
        $config = $this->getConfig($name); 
        //$config=[ 'driver' => 'session', 'provider' => 'users']

        if (is_null($config)) {
            throw new InvalidArgumentException("Auth guard [{$name}] is not defined.");
        }

        
        if (isset($this->customCreators[$config['driver']])) {

            return $this->callCustomCreator($name, $config);
        }
         //$driverMethod=createSessionDriver
        $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.");
    }

由上面可以知道,最后跑到了createSessionDriver这个方法了:

//$config=[ 'driver' => 'session', 'provider' => 'users']

 public function createSessionDriver($name, $config)
    {
        //$provider=EloquentUserProvider($this->app['hash'], $config['model']);
        
        $provider = $this->createUserProvider($config['provider'] ?? null);

        $guard = new SessionGuard($name, $provider, $this->app['session.store']);

       
        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;
    }
    
    
    
      public function createUserProvider($provider = null)
    {
    //$provider=user
        if (is_null($config = $this->getProviderConfiguration($provider))) {
            return;
        }
        
    //$config=  ['driver' => 'eloquent','model' => App\User::class,]
    //我们没有自定义自己的提供器,所以这一坨跳过,那么怎么自定义自己的呢,使用Auth::provider
    //
    //public function provider($name, Closure $callback)
    //{
    //    $this->customProviderCreators[$name] = $callback;
    //
    //      return $this;
    //  } 
    // 具体可以看文档https://d.laravel-china.org/docs/5.5/authentication

        if (isset($this->customProviderCreators[$driver = ($config['driver'] ?? null)])) {
            return call_user_func(
                $this->customProviderCreators[$driver], $this->app, $config
            );
        }

      //$driver=eloquent
        switch ($driver) {
            case 'database':
                return $this->createDatabaseProvider($config);
            case 'eloquent':
            //return new EloquentUserProvider($this->app['hash'], $config['model']);
                return $this->createEloquentProvider($config);
            default:
                throw new InvalidArgumentException(
                    "Authentication user provider [{$driver}] is not defined."
                );
        }
    }

所以Auth::guard()最后返回一个SessionGuard实例,接着看一下sessionGuard里面找一下attempt方法:

// $this->guard()->attempt($this->credentials($request), $request->has('remember'));

  public function attempt(array $credentials = [], $remember = false)
    {
        //很任性的不管
        $this->fireAttemptEvent($credentials, $remember);

      //$this->provider 就是上面的 EloquentUserProvider($this->app['hash'], $config['model']);
      //具体就是查找用户,太简单了,不说了
        $this->lastAttempted = $user = $this->provider->retrieveByCredentials($credentials);

        //这里就是验证用户密码是不是相同的地方
        if ($this->hasValidCredentials($user, $credentials)) {
            $this->login($user, $remember);

            return true;
        }

        $this->fireFailedEvent($user, $credentials);

        return false;
    }
    
     protected function hasValidCredentials($user, $credentials)
    {
        return ! is_null($user) && $this->provider->validateCredentials($user, $credentials);
    }

可以看最后是在EloquentUserProvider 里面验证了用户的密码是不是相同:

 public function validateCredentials(UserContract $user, array $credentials)
    {
        $plain = $credentials['password'];

        return $this->hasher->check($plain, $user->getAuthPassword());
    }

所有到这里我们就找到问题的根源了(你说是不是很蛋疼,找一个问题费老大劲),那么我们要解决旧系统的密码加密问题,有两个办法:

  • 自定义用户提供器(目前不就是使用的EloquentUserProvider,’我们自定义一个,再重写一下validateCredentials就可以了)
  • 重写 $this->hasher

感觉一次写的有点多了,下次在写具体方法吧

    原文作者:soledad
    原文地址: https://segmentfault.com/a/1190000011277321
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞