Laravel Auth의 원리에 대한 간략한 분석

藏色散人
풀어 주다: 2020-08-07 16:01:02
앞으로
4177명이 탐색했습니다.

다음은 Laravel튜토리얼 칼럼에서 Laravel Auth의 원리를 간략하게 분석한 내용입니다. 도움이 필요한 친구들에게 도움이 되길 바랍니다!

Laravel Auth의 원리에 대한 간략한 분석

회사에서 최근 Laravel-admin을 백엔드로 사용하고 Laravel 프레임워크를 노출한 이후로 Laravel 커뮤니티의 힘과 생태계는 정말 강력하다고 말씀드리고 싶습니다.

 하지만 회사 내부 업무는 모두 Java 쪽이고 백엔드도 모두 JavaApi를 조정하고 있어서 Laravel의 기능을 대폭 줄여야 합니다. 우선 Eloquent 모델을 전혀 사용할 수 없습니다. 여기에는 3개의 테이블만 저장되어 있습니다. 이것은 Laravel-admin과 함께 제공되는 테이블입니다.

Laravel Auth의 원리에 대한 간략한 분석

Laravel-admin에는 9개의 테이블이 제공됩니다. 사용자 로그인 업무가 모두 API 측에 저장되므로 내장된 테이블 기능을 포기했습니다. 따라서 Api 로그인 로직을 직접 구현해야 하며, Laravel Auth 인증을 사용해야 합니다.

원리 해석

// 使用下面这个命令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는 시스템의 싱글톤이고 프로토타입은

Illuminate\Auth\AuthManager;
로그인 후 복사

에 있습니다. 이름에서 알 수 있듯이 인증 관리 모듈이며 인증 팩토리 모드 인터페이스를 구현합니다. 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' => App\User::class,
        ],
        // 'users' => [
        //     'driver' => 'database',
        //     'table' => 'users',
        // ],
    ],
로그인 후 복사

구성 파일을 살펴보세요. ), 기본 구성에서 sessionGuard를 반환했습니다.

주로 다음 4가지 방법을 살펴보세요

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());
    }
}
로그인 후 복사

일반적으로 사용자 로그인 프로세스는 완료됩니다.

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

만 가능한 컨트롤러/방법을 구현합니다. 로그인 후 접속

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;
    }
로그인 후 복사

처음 써보는데 오류가 있네요 지적해주시고 감사합니다!

위 내용은 Laravel Auth의 원리에 대한 간략한 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:zhihu.com
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿