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.
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, Auth
So 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
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); } }
$this->post('register', 'Auth\RegisterController@register');
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']), ]); } }
an einer beliebigen Stelle in der Anwendung abrufen. Auth::user()
$this->post('login', 'Auth\LoginController@login');
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'); } }
-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); } }
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 retriveBycredentials
validateCredentials
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); } }
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. check
password_verify
Nachdem 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
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::extend
Auth::provider
Im 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-ServicecontainerDas obige ist der detaillierte Inhalt vonImplementierungsdetails des Laravel-Benutzerauthentifizierungssystems. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!