Ausführliche Erklärung, wie Laravel die Salt- und Passwort-Authentifizierung durch Modifizieren von Auth verwendet

*文
Freigeben: 2023-03-19 08:30:01
Original
2463 Leute haben es durchsucht

Dieser Artikel führt Sie hauptsächlich in die relevanten Informationen zur Authentifizierung von Benutzern durch Ändern von Laravel Auth ein. Es hat einen gewissen Referenzlernwert für alle, die lernen oder arbeiten Brauchen Sie es? Schauen wir uns unten gemeinsam einen Blick darauf. Ich hoffe, es hilft allen.

Vorwort

In diesem Artikel wird hauptsächlich der relevante Inhalt der Änderung von Laravel Auth zur Verwendung von Salt und Passwort zur Authentifizierung von Benutzern vorgestellt und geteilt Ich werde im Folgenden nicht viel sagen. Schauen wir uns die ausführliche Einführung an:

Laravals eigenes Benutzerauthentifizierungssystem Auth ist sehr leistungsstark und einfach zu verwenden Die Passwortverschlüsselungs- und Authentifizierungsalgorithmen von Laravel, die in Modulen wie , Login und Passwortabruf verwendet werden, verwenden alle bcrypt, und viele frühere Projekte verwenden die Methode zum Speichern von Salt + Passwort-verschlüsselten Zeichenfolgen, um Benutzerpasswörter in der Benutzertabelle aufzuzeichnen Ich habe die Änderung von Laravel Auth kürzlich abgeschlossen, indem ich im Internet nach Informationen gesucht und mir den Quellcode angesehen habe es hilft anderen. Bevor ich anfange, muss ich erklären, dass bei Verwendung des Laravel-Frameworks in einem neuen Projekt keine Änderungen an Auth vorgenommen werden müssen. Der Standard-Verschlüsselungsalgorithmus von bcrypt ist ein sichererer und effizienterer Verschlüsselungsalgorithmus als Salt + Passwort.

Benutzerregistrierung ändern

Aktivieren Sie zunächst die Verifizierung in Laravel mit dem artisan-Befehl

php artisan make:auth
Nach dem Login kopieren

Danach Beim Ausführen des Befehls gibt es einen zusätzlichen statischen Methodenaufruf in der Routendatei (Speicherort: app/Http/routes.php)

Route::auth();
Nach dem Login kopieren

Diese Route ist eine Fassade von Laravel (befindet sich in IlluminateSupportFacadesRoute) und Die Authentifizierungsmethode heißt. Sie ist in der IlluminateRoutingRouter-Klasse definiert. Wie Sie unten sehen können, definiert die Authentifizierungsmethode einige Authentifizierungs-bezogene Routing-Regeln.

/**
 * Register the typical authentication routes for an application.
 *
 * @return void
 */
public function auth()
{
 // Authentication Routes...
 $this->get('login', 'Auth\AuthController@showLoginForm');
 $this->post('login', 'Auth\AuthController@login');
 $this->get('logout', 'Auth\AuthController@logout');

 // Registration Routes...
 $this->get('register', 'Auth\AuthController@showRegistrationForm');
 $this->post('register', 'Auth\AuthController@register');

 // Password Reset Routes...
 $this->get('password/reset/{token?}', 'Auth\PasswordController@showResetForm');
 $this->post('password/email', 'Auth\PasswordController@sendResetLinkEmail');
 $this->post('password/reset', 'Auth\PasswordController@reset');
}
Nach dem Login kopieren

Anhand der Routing-Regeln können Sie sehen, dass die Controller-Methode Bei der Registrierung wird die Registermethode von AuthControllers in den Merkmalen IlluminateFoundationAuthRegistersUsers angefordert.

/**
 * Handle a registration request for the application.
 *
 * @param \Illuminate\Http\Request $request
 * @return \Illuminate\Http\Response
 */
public function register(Request $request)
{
 $validator = $this->validator($request->all());

 if ($validator->fails()) {
 $this->throwValidationException(
  $request, $validator
 );
 }

 Auth::guard($this->getGuard())->login($this->create($request->all()));

 return redirect($this->redirectPath());
}
Nach dem Login kopieren

In der Registermethode werden die Benutzereingabedaten eingegeben Zuerst müssen Sie nur Ihre eigenen Validierungsregeln für jedes Eingabefeld in der Validierungsmethode definieren

protected function validator(array $data)
{
 return Validator::make($data, [
 'name' => 'required|max:255',
 'email' => 'required|email|max:255|unique:user',
 'password' => 'required|size:40|confirmed',
 ]);
}
Nach dem Login kopieren

Schauen Sie dann nach unten und sehen Sie, dass Laravel nach bestandener Überprüfung die Erstellungsmethode von verwendet AuthController generiert einen neuen Benutzer und übernimmt dann den neuen Benutzer. Verwenden Sie die Daten, um sich anzumelden Auth::guard($this->getGuard())->login($this->create($request->all()));

Wenn wir also die Verschlüsselungsmethode zum Generieren von Benutzerkennwörtern während der Benutzerregistrierung anpassen möchten, müssen wir nur Änderungen vornehmen die Erstellungsmethode von AuthController.

Zum Beispiel:

/**
 * Create a new user instance after a valid registration.
 *
 * @param array $data
 * @return User
 */
protected function create(array $data)
{
 $salt = Str::random(6);
 return User::create([
 'nickname' => $data['name'],
 'email' => $data['email'],
 'password' => sha1($salt . $data['password']),
 'register_time' => time(),
 'register_ip' => ip2long(request()->ip()),
 'salt' => $salt
 ]);
}
Nach dem Login kopieren

Benutzeranmeldung ändern

Wir müssen die ändern Zuerst anmelden Schauen Sie sich den spezifischen Controller und die Methode der Anmeldeanforderung anhand der Routing-Regeln an. In der oben genannten Authentifizierungsmethodendefinition können Sie sehen, dass die Überprüfung der Anmeldung in der Anmeldemethode der AppHttpControllersAuthAuthController-Klasse erfolgt. Öffnen Sie AuthController und stellen Sie fest, dass Auth-bezogene Methoden über Merkmale in die Klasse eingeführt werden. Während der Kompilierung kopiert PHP den Code in den Merkmalen Anwendbare Szenarien und Verwendungsmöglichkeiten der eingeführten Funktionen werden hier nicht detailliert beschrieben. Die

-Methode ist tatsächlich in den
 $this->get('login', 'Auth\AuthController@showLoginForm');
 $this->post('login', 'Auth\AuthController@login');
 $this->get('logout', 'Auth\AuthController@logout');
Nach dem Login kopieren
IlluminateFoundationAuthenticatesUsers-Eigenschaften definiert. Der Hauptvorgang der Anmeldeüberprüfung wird im

-Methodenaufruf durchgeführt. Es handelt sich um IlluminateAuthSessionGuard (siehe den Quellcode in der Auth-Fassade IlluminateAuthAuthManager). Details dazu, wie Sie es erhalten) 以AuthController@login
Sehen Sie sich an, wie die Versuchsmethode in SessionGuard implementiert ist:

/**
 * Handle a login request to the application.
 *
 * @param \Illuminate\Http\Request $request
 * @return \Illuminate\Http\Response
 */
public function login(Request $request)
{
 $this->validateLogin($request);
 $throttles = $this->isUsingThrottlesLoginsTrait();

 if ($throttles && $lockedOut = $this->hasTooManyLoginAttempts($request)) {
 $this->fireLockoutEvent($request);

 return $this->sendLockoutResponse($request);
 }

 $credentials = $this->getCredentials($request);

 if (Auth::guard($this->getGuard())->attempt($credentials, $request->has('remember'))) {
 return $this->handleUserWasAuthenticated($request, $throttles);
 }

 if ($throttles && ! $lockedOut) {
 $this->incrementLoginAttempts($request);
 }

 return $this->sendFailedLoginResponse($request);
}
Nach dem Login kopieren

retrieveByCredentials ist das Feld, das von übergeben wird. Um Benutzerdaten aus der Datenbank abzurufen, ist validateCredentials der eigentliche Prozess, der verwendet wird, um zu überprüfen, ob das Passwort korrekt ist. Auth::guard($this->getGuard())->attempt($credentials, $request->has('remember'));Auth::guard($this->getGuard()) Was hier beachtet werden muss, ist, dass

Dieser Anbieter ist ein Anbieter, der die IlluminateContractsAuthUserProvider-Klasse implementiert. Wir sehen, dass es im Verzeichnis IlluminateAuth zwei UserProvider-Implementierungen gibt, nämlich DatabaseUserProvider und EloquentUserProvider, aber wenn wir es überprüfen Das Passwort wird dadurch überprüft

public function attempt(array $credentials = [], $remember = false, $login = true)
{
 $this->fireAttemptEvent($credentials, $remember, $login);

 $this->lastAttempted = $user = $this->provider->retrieveByCredentials($credentials);

 if ($this->hasValidCredentials($user, $credentials)) {
 if ($login) {
  $this->login($user, $remember);
 }

 return true;
 }

 if ($login) {
 $this->fireFailedEvent($user, $credentials);
 }

 return false;
}

/**
 * Determine if the user matches the credentials.
 *
 * @param mixed $user
 * @param array $credentials
 * @return bool
 */

protected function hasValidCredentials($user, $credentials)
{
 return ! is_null($user) && $this->provider->validateCredentials($user, $credentials);
}
Nach dem Login kopieren
Die Konfiguration wird hier durch „retrieveByCredentials“ von EloquentUserProvider überprüft instanziiert. Eingefügt (genauer gesagt, wie der entsprechende Anbieter durch Lesen der Authentifizierungskonfigurationsdatei in SessionGuard eingefügt wird, siehe Quellcode der Methode createSessionDriver in IlluminateAuthAuthManager)

Als nächstes schauen wir uns weiterhin RecoverByCredentials und EloquentUserProvider an Implementierung der Methode „validateCredentials“:

/**
 * Retrieve a user by the given credentials.
 *
 * @param array $credentials
 * @return \Illuminate\Contracts\Auth\Authenticatable|null
 */
public function retrieveByCredentials(array $credentials)
{
 if (empty($credentials)) {
 return;
 }

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

/**
 * Validate a user against the given credentials.
 *
 * @param \Illuminate\Contracts\Auth\Authenticatable $user
 * @param array $credentials
 * @return bool
 */
public function validateCredentials(UserContract $user, array $credentials)
{
 $plain = $credentials['password'];

 return $this->hasher->check($plain, $user->getAuthPassword());
}
Nach dem Login kopieren

上面两个方法retrieveByCredentials用除了密码以外的字段从数据库用户表里取出用户记录,比如用email查询出用户记录,然后validateCredentials方法就是通过$this->haser->check来将输入的密码和哈希的密码进行比较来验证密码是否正确。

好了, 看到这里就很明显了, 我们需要改成自己的密码验证就是自己实现一下validateCredentials就可以了, 修改$this->hasher->check为我们自己的密码验证规则就可以了。

首先我们修改$user->getAuthPassword()把数据库中用户表的salt和password传递到validateCredentials中
修改App\User.php 添加如下代码

/**
 * The table associated to this model
 */
protected $table = 'user';//用户表名不是laravel约定的这里要指定一下
Nach dem Login kopieren
/**
 * 禁用Laravel自动管理timestamp列
 */
public $timestamps = false;

/**
 * 覆盖Laravel中默认的getAuthPassword方法, 返回用户的password和salt字段
 * @return type
 */
public function getAuthPassword()
{
 return ['password' => $this->attributes['password'], 'salt' => $this->attributes['salt']];
}
Nach dem Login kopieren

然后我们在建立一个自己的UserProvider接口的实现,放到自定义的目录中:

新建app/Foundation/Auth/AdminEloquentUserProvider.php

namespace App\Foundation\Auth;

use Illuminate\Auth\EloquentUserProvider;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Support\Str;

class AdminEloquentUserProvider extends EloquentUserProvider
{

 /**
  * Validate a user against the given credentials.
  *
  * @param \Illuminate\Contracts\Auth\Authenticatable $user
  * @param array $credentials
  */
 public function validateCredentials(Authenticatable $user, array $credentials) {
  $plain = $credentials['password'];
  $authPassword = $user->getAuthPassword();

  return sha1($authPassword['salt'] . $plain) == $authPassword['password'];
 }
}
Nach dem Login kopieren

最后我们修改auth配置文件让Laravel在做Auth验证时使用我们刚定义的Provider,
修改config/auth.php:

'providers' => [
 'users' => [
  'driver' => 'admin-eloquent',
  'model' => App\User::class,
 ]
]
Nach dem Login kopieren

修改app/Provider/AuthServiceProvider.php

public function boot(GateContract $gate)
{
 $this->registerPolicies($gate);

 \Auth::provider('admin-eloquent', function ($app, $config) {
  return New \App\Foundation\Auth\AdminEloquentUserProvider($app['hash'], $config['model']);
 });
}
Nach dem Login kopieren

Auth::provider方法是用来注册Provider构造器的,这个构造器是一个Closure,provider方法的具体代码实现在AuthManager文件里

public function provider($name, Closure $callback)
{
 $this->customProviderCreators[$name] = $callback;

 return $this;
}
Nach dem Login kopieren

闭包返回了AdminEloquentUserProvider对象供Laravel Auth使用,好了做完这些修改后Laravel的Auth在做用户登录验证的时候采用的就是自定义的salt + password的方式了。

修改重置密码

Laravel 的重置密码的工作流程是:

  • 向需要重置密码的用户的邮箱发送一封带有重置密码链接的邮件,链接中会包含用户的email地址和token。

  • 用户点击邮件中的链接在重置密码页面输入新的密码,Laravel通过验证email和token确认用户就是发起重置密码请求的用户后将新密码更新到用户在数据表的记录里。

第一步需要配置Laravel的email功能,此外还需要在数据库中创建一个新表password_resets来存储用户的email和对应的token

CREATE TABLE `password_resets` (
 `email` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
 `token` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
 `created_at` timestamp NOT NULL,
 KEY `password_resets_email_index` (`email`),
 KEY `password_resets_token_index` (`token`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Nach dem Login kopieren

通过重置密码表单的提交地址可以看到,表单把新的密码用post提交给了/password/reset,我们先来看一下auth相关的路由,确定/password/reset对应的控制器方法。

 $this->post('password/reset', 'Auth\PasswordController@reset');
Nach dem Login kopieren

可以看到对应的控制器方法是\App\Http\Controllers\Auth\PasswordController类的reset方法,这个方法实际是定义在\Illuminate\Foundation\Auth\ResetsPasswords 这个traits里,PasswordController引入了这个traits

/**
 * Reset the given user's password.
 *
 * @param \Illuminate\Http\Request $request
 * @return \Illuminate\Http\Response
 */
public function reset(Request $request)
{
 $this->validate(
  $request,
  $this->getResetValidationRules(),
  $this->getResetValidationMessages(),
  $this->getResetValidationCustomAttributes()
 );

 $credentials = $this->getResetCredentials($request);

 $broker = $this->getBroker();

 $response = Password::broker($broker)->reset($credentials, function ($user, $password) {
  $this->resetPassword($user, $password);
 });

 switch ($response) {
  case Password::PASSWORD_RESET:
   return $this->getResetSuccessResponse($response);
  default:
   return $this->getResetFailureResponse($request, $response);
 }
}
Nach dem Login kopieren

方法开头先通过validator对输入进行验证,接下来在程序里传递把新密码和一个闭包对象传递给Password::broker($broker)->reset();方法,这个方法定义在\Illuminate\Auth\Passwords\PasswordBroker类里.

/**
 * Reset the password for the given token.
 *
 * @param array $credentials
 * @param \Closure $callback
 * @return mixed
 */
public function reset(array $credentials, Closure $callback)
{
 // If the responses from the validate method is not a user instance, we will
 // assume that it is a redirect and simply return it from this method and
 // the user is properly redirected having an error message on the post.
 $user = $this->validateReset($credentials);

 if (! $user instanceof CanResetPasswordContract) {
  return $user;
 }

 $pass = $credentials['password'];

 // Once we have called this callback, we will remove this token row from the
 // table and return the response from this callback so the user gets sent
 // to the destination given by the developers from the callback return.
 call_user_func($callback, $user, $pass);

 $this->tokens->delete($credentials['token']);

 return static::PASSWORD_RESET;
}
Nach dem Login kopieren

在PasswordBroker的reset方法里,程序会先对用户提交的数据做再一次的认证,然后把密码和用户实例传递给传递进来的闭包,在闭包调用里完成了将新密码更新到用户表的操作, 在闭包里程序调用了的PasswrodController类的resetPassword方法

function ($user, $password) {
 $this->resetPassword($user, $password);
});
Nach dem Login kopieren

PasswrodController类resetPassword方法的定义

protected function resetPassword($user, $password)
{
 $user->forceFill([
  'password' => bcrypt($password),
  'remember_token' => Str::random(60),
 ])->save();

 Auth::guard($this->getGuard())->login($user);
}
Nach dem Login kopieren

在这个方法里Laravel 用的是bcrypt 加密了密码, 那么要改成我们需要的salt + password的方式,我们在PasswordController类里重写resetPassword方法覆盖掉traits里的该方法就可以了。

/**
 * 覆盖ResetsPasswords traits里的resetPassword方法,改为用sha1(salt + password)的加密方式
 * Reset the given user's password.
 *
 * @param \Illuminate\Contracts\Auth\CanResetPassword $user
 * @param string $password
 * @return void
 */
protected function resetPassword($user, $password)
{
 $salt = Str::random(6);
 $user->forceFill([
  'password' => sha1($salt . $password),
  'salt' => $salt,
  'remember_token' => Str::random(60),
 ])->save();

 \Auth::guard($this->getGuard())->login($user);
}
Nach dem Login kopieren

结语

到这里对Laravel Auth的自定义就完成了,注册、登录和重置密码都改成了sha1(salt + password)的密码加密方式, 所有自定义代码都是通过定义Laravel相关类的子类和重写方法来完成没有修改Laravel的源码,这样既保持了良好的可扩展性也保证了项目能够自由迁移。

注:使用的Laravel版本为5.2

相关推荐:

Laravel 5.5的可相应接口如何使用?

Laravel Redis 多个进程同时取队列问题

laravel编写APP接口(API)

Das obige ist der detaillierte Inhalt vonAusführliche Erklärung, wie Laravel die Salt- und Passwort-Authentifizierung durch Modifizieren von Auth verwendet. 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