Implementierungsdetails des Laravel-Benutzerauthentifizierungssystems

不言
Freigeben: 2023-04-02 16:56:01
Original
2257 Leute haben es durchsucht

Dieser Artikel stellt hauptsächlich die Implementierungsdetails des Laravel-Benutzerauthentifizierungssystems vor, das einen gewissen Referenzwert hat. Jetzt kann ich ihn mit allen teilen, die ihn benötigen.

Implementierungsdetails des Benutzerauthentifizierungssystems

Im vorherigen Abschnitt haben wir die Grundkenntnisse des Laravel Auth-Systems vorgestellt und über seine Kernkomponenten gesprochen. In diesem Abschnitt konzentrieren wir uns auf die Implementierungsdetails des Laravel Auth-Systems und konzentrieren uns hauptsächlich darauf ist, AuthSo laden Sie den Authentifizierungsschutz (Guard) und den Benutzeranbieter (UserProvider) sowie die Implementierungsdetails der Standardbenutzerregistrierung und -anmeldung. Durch Sortieren dieser Implementierungsdetails können wir auch wissen, wie die Auth-Authentifizierung angepasst wird erfüllen unsere eigenen Projekte Anforderungen an die Benutzerauthentifizierung. AuthManager

Laden des Watcher- und Benutzeranbieters über AuthManager

AuthManager verwendet viele Methoden zum Laden des Watcher- und Benutzeranbieters, und die Beschreibung in Worten ist nicht klar. Wir verwenden Anmerkungen in dieser Prozessmethode, um sie anzuzeigen die spezifischen Implementierungsdetails.

namespace Illuminate\Auth;

class AuthManager implements FactoryContract
{
    /**
     * 尝试从$guards属性中获取指定的Guard
     *
     * @param  string  $name
     * @return \Illuminate\Contracts\Auth\Guard|\Illuminate\Contracts\Auth\StatefulGuard
     */
    public function guard($name = null)
    {
        $name = $name ?: $this->getDefaultDriver();

        return isset($this->guards[$name])
                    ? $this->guards[$name]
                    : $this->guards[$name] = $this->resolve($name);
    }
    
    /**
     * 解析出给定name的Guard
     *
     * @param  string  $name
     * @return \Illuminate\Contracts\Auth\Guard|\Illuminate\Contracts\Auth\StatefulGuard
     *
     * @throws \InvalidArgumentException
     */
    protected function resolve($name)
    {
        //获取Guard的配置
        //$config = ['driver' => 'session', 'provider' => 'users']
        $config = $this->getConfig($name);

        if (is_null($config)) {
            throw new InvalidArgumentException("Auth guard [{$name}] is not defined.");
        }
       //如果通过extend方法为guard定义了驱动器,这里去调用自定义的Guard驱动器
        if (isset($this->customCreators[$config['driver']])) {
            return $this->callCustomCreator($name, $config);
        }
        //Laravel auth默认的配置这里是执行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.");
    }
    
    /**
     * 从config/auth.php中获取给定名称的Guard的配置
     *
     * @param  string  $name
     * @return array
     */
    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],

        'api' => [
            'driver' => 'token',
            'provider' => 'users',
        ],
    ],
    protected function getConfig($name)
    {
        //'guards' => [
        //    'web' => [
        //        'driver' => 'session',
        //        'provider' => 'users',
        //    ],

        //    'api' => [
        //        'driver' => 'token',
        //        'provider' => 'users',
        //    ],
        //],
        // 根据Laravel默认的auth配置, 这个方法会获取key "web"对应的数组
        return $this->app['config']["auth.guards.{$name}"];
    }
    
    /**
     * 调用自定义的Guard驱动器
     *
     * @param  string  $name
     * @param  array  $config
     * @return mixed
     */
    protected function callCustomCreator($name, array $config)
    {
        return $this->customCreators[$config['driver']]($this->app, $name, $config);
    }
    
    /**
     * 注册一个自定义的闭包Guard 驱动器 到customCreators属性中
     *
     * @param  string  $driver
     * @param  \Closure  $callback
     * @return $this
     */
    public function extend($driver, Closure $callback)
    {
        $this->customCreators[$driver] = $callback;

        return $this;
    }
    
    /**
     * 注册一个自定义的用户提供器创建器到 customProviderCreators属性中
     *
     * @param  string  $name
     * @param  \Closure  $callback
     * @return $this
     */
    public function provider($name, Closure $callback)
    {
        $this->customProviderCreators[$name] = $callback;

        return $this;
    }
    
    /**
     * 创建基于session的认证看守器 SessionGuard
     *
     * @param  string  $name
     * @param  array  $config
     * @return \Illuminate\Auth\SessionGuard
     */
    public function createSessionDriver($name, $config)
    {
        //$config['provider'] == 'users'
        $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;
    }
    
    //创建Guard驱动依赖的用户提供器对象
    public function createUserProvider($provider = null)
    {
        if (is_null($config = $this->getProviderConfiguration($provider))) {
            return;
        }
        //如果通过Auth::provider方法注册了自定义的用户提供器creator闭包则去调用闭包获取用户提供器对象
        if (isset($this->customProviderCreators[$driver = ($config['driver'] ?? null)])) {
            return call_user_func(
                $this->customProviderCreators[$driver], $this->app, $config
            );
        }

        switch ($driver) {
            case 'database':
                return $this->createDatabaseProvider($config);
            case 'eloquent':
                //通过默认的auth配置这里会返回EloquentUserProvider对象,它实现了Illuminate\Contracts\Auth 接口
                return $this->createEloquentProvider($config);
            default:
                throw new InvalidArgumentException(
                    "Authentication user provider [{$driver}] is not defined."
                );
        }
    }
    
    /**
     * 会通过__call去动态地调用AuthManager代理的Guard的用户认证相关方法
     * 根据默认配置,这里__call会去调用SessionGuard里的方法
     * @param  string  $method
     * @param  array  $parameters
     * @return mixed
     */
    public function __call($method, $parameters)
    {
        return $this->guard()->{$method}(...$parameters);
    }
}
Nach dem Login kopieren

Registrierter Benutzer

Die Standardregistrierungsroute im Laravel Auth-System ist wie folgt:

$this->post('register', 'Auth\RegisterController@register');
Nach dem Login kopieren

Die Logik der Benutzerregistrierung wird also durch die Registermethode von RegisterController vervollständigt

class RegisterController extends Controller
{
    //方法定义在Illuminate\Foundation\Auth\RegisterUsers中
    public function register(Request $request)
    {
        $this->validator($request->all())->validate();

        event(new Registered($user = $this->create($request->all())));

        $this->guard()->login($user);

        return $this->registered($request, $user)
        
     }
     
    protected function validator(array $data)
    {
        return Validator::make($data, [
            'name' => 'required|string|max:255',
            'email' => 'required|string|email|max:255|unique:users',
            'password' => 'required|string|min:6|confirmed',
        ]);
    }
    
    protected function create(array $data)
    {
        return User::create([
            'name' => $data['name'],
            'email' => $data['email'],
            'password' => bcrypt($data['password']),
        ]);
    }
         
}
Nach dem Login kopieren

Der Registrierungsprozess ist sehr einfach. Er besteht darin, zu überprüfen, ob die vom Benutzer eingegebenen Daten korrekt sind, und dann die Daten in die Datenbank zu schreiben, um den bcrypt-Algorithmus zu verwenden Sie müssen es in den häufig verwendeten Salt-Verschlüsselungs-Klartext für Hashing ändern. Die Passwortverschlüsselungsmethode kann diesen Teil der Logik in der Erstellungsmethode ändern. Nach der Registrierung des Benutzers wird die Anmeldemethode von SessionGuard aufgerufen, um die Benutzerdaten in die zu laden Beachten Sie, dass diese Anmeldemethode keine Anmeldeauthentifizierung hat, sondern nur den authentifizierten Benutzer in die Anwendung lädt. Wir können Benutzerdaten über

an einer beliebigen Stelle in der Anwendung abrufen. Auth::user()

Benutzeranmeldeauthentifizierung

Die Anmelderoute des Laravel Auth-Systems ist wie folgt

$this->post('login', 'Auth\LoginController@login');
Nach dem Login kopieren

Werfen wir einen Blick auf die Anmeldelogik in LoginController

class LoginController extends Controller
{
    /**
     * 处理登录请求
     */
    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->filled('remember')
        );
    }
    
    //获取登录用的字段值
    protected function credentials(Request $request)
    {
        return $request->only($this->username(), 'password');
    }
}
Nach dem Login kopieren

Wie Sie sehen können, wird die Logik der Anmeldeauthentifizierung über die

-Methode von SessionGuard implementiert. Schauen wir uns die Logik in der attempt-Methode an: Auth::attempt()

class SessionGuard implements StatefulGuard, SupportsBasicAuth
{
    public function attempt(array $credentials = [], $remember = false)
    {
        $this->fireAttemptEvent($credentials, $remember);

        $this->lastAttempted = $user = $this->provider->retrieveByCredentials($credentials);
       //如果登录认证通过,通过login方法将用户对象装载到应用里去
        if ($this->hasValidCredentials($user, $credentials)) {
            $this->login($user, $remember);

            return true;
        }
        //登录失败的话,可以触发事件通知用户有可疑的登录尝试(需要自己定义listener来实现)
        $this->fireFailedEvent($user, $credentials);

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

s

-Methode Zunächst werden die Benutzerdaten aus der Benutzertabelle über den Benutzernamen über die SessionGuard-Methode des Benutzeranbieters abgefragt. Die Authentifizierungsbenutzerinformationen werden über die attempt des Benutzeranbieters implementiert Alle Benutzeranbieter-Implementierungsklassen implementieren den UserProvider-Vertrag (Schnittstelle). Durch die obige Analyse wissen wir, dass der Standardbenutzeranbieter retriveBycredentialsvalidateCredentials

class EloquentUserProvider implements UserProvider
{
    从数据库中取出用户实例
    public function retrieveByCredentials(array $credentials)
    {
        if (empty($credentials) ||
           (count($credentials) === 1 &&
            array_key_exists('password', $credentials))) {
            return;
        }

        $query = $this->createModel()->newQuery();

        foreach ($credentials as $key => $value) {
            if (! Str::contains($key, 'password')) {
                $query->where($key, $value);
            }
        }

        return $query->first();
    }
    
    //通过给定用户认证数据来验证用户
    public function validateCredentials(UserContract $user, array $credentials)
    {
        $plain = $credentials['password'];

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

class BcryptHasher implements HasherContract
{
    //通过bcrypt算法计算给定value的散列值
    public function make($value, array $options = [])
    {
        $hash = password_hash($value, PASSWORD_BCRYPT, [
            'cost' => $this->cost($options),
        ]);

        if ($hash === false) {
            throw new RuntimeException('Bcrypt hashing not supported.');
        }

        return $hash;
    }
    
    //验证散列值是否给定明文值通过bcrypt算法计算得到的
    public function check($value, $hashedValue, array $options = [])
    {
        if (strlen($hashedValue) === 0) {
            return false;
        }

        return password_verify($value, $hashedValue);
    }
}
Nach dem Login kopieren
EloquentUserProvider ist. Die Überprüfung des Benutzerkennworts wird durch den

-Hasher abgeschlossen Das

hängt davon ab, dass das Laravel-Authentifizierungssystem standardmäßig den bcrypt-Algorithmus verwendet, um das vom Benutzer bereitgestellte Klartextkennwort zu verschlüsseln und es dann in der Benutzertabelle zu speichern. Während der Überprüfung verwendet die EloquentUserProvider-Methode des hasher Hashers In PHP integrierte Methode haser, um zu überprüfen, ob das Klartext-Passwort der ursprüngliche Wert des gespeicherten Chiffretext-Passworts ist. checkpassword_verifyNachdem wir die wichtigsten Details des Benutzerauthentifizierungssystems geklärt haben, wissen wir, wie wir unseren eigenen Wächter (Guard) oder Benutzeranbieter (UserProvider) definieren. Zuerst müssen sie die Methoden im Vertrag implementieren, die sie jeweils einhalten Stellen Sie eine nahtlose Verbindung zum Auth-System von Laravel her. Anschließend müssen Sie Ihren eigenen Guard oder Provider über die Methoden

und

registrieren, um die Schließung der Guard- oder Provider-Instanz an Laravel zurückzugeben Es muss kein vollständiger Satz sein. Wir können den Guard separat anpassen und trotzdem den Standard-EloquentUserProvider verwenden oder den Standard-SessionGuard einen benutzerdefinierten UserProvider verwenden lassen. Auth::extendAuth::providerIm nächsten Abschnitt werde ich einen Fall vorstellen, der in unserer vorherigen Projektentwicklung verwendet wurde, um besser zu erklären, wie das Laravel Auth-System erweitert werden kann.

Das Obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, er wird für das Studium aller hilfreich sein. Weitere verwandte Inhalte finden Sie auf der chinesischen PHP-Website.

Verwandte Empfehlungen:

Das Laravel WeChat-Applet erhält Benutzerdetails und analysiert die Applet-Code-Erweiterung mit Parametern


Vorteile der Verwendung Laravel-Servicecontainer

Das obige ist der detaillierte Inhalt vonImplementierungsdetails des Laravel-Benutzerauthentifizierungssystems. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!