Preface
This article mainly introduces relevant content about Laravel user multi-field authentication, and shares it for your reference and learning. I won’t say much below, let’s take a look at the detailed introduction together.
Solution:
- No more than two login fields (simple solution)
- Login fields are greater than or equal to three (relatively more complicated)
No more than two login fields
I've seen a relatively simple solution online, but it can't solve the verification of all two fields:
filter_var($request->input('login'), FILTER_VALIDATE_EMAIL) ? 'email' : 'name'
Filter the form content in the request to distinguish username. The disadvantages are obvious. If the other one is not an email, you will be blind... Here is another common solution:
Override the login method in LoginController
public function login(Requests $request) { //Suppose the field is email if ($this->guard()->attempt($request->only('email', 'password'))) { return $this->sendLoginResponse($request); } //Suppose the field is mobile if ($this->guard()->attempt($request->only('mobile', 'password'))) { return $this->sendLoginResponse($request); } //Suppose the field is username if ($this->guard()->attempt($request->only('username', 'password'))) { return $this->sendLoginResponse($request); } return $this->sendFailedLoginResponse($request); }
It can be seen that although it can solve the problem, it is obviously contrary to Laravel's elegant style. After so much trouble, I will share my solution with you below.
Login fields are greater than or equal to three (relatively more complicated)
First, you need to implement an Illuminate\Contracts\Auth\UserProvider implementation yourself. For details, please refer toAdd a custom user providerBut I like to be lazy, so I directly inherited the EloquentUserProvider and rewritten the retrieveByCredentials method:
public function retrieveByCredentials(array $credentials) { if (empty($credentials)) { return; } // First we will add each credential element to the query as a where clause. // Then we can execute the query and, if we found a user, return it in a // Eloquent User "model" that will be utilized by the Guard instances. $query = $this->createModel()->newQuery(); foreach ($credentials as $key => $value) { if (! Str::contains($key, 'password')) { $query->orWhere($key, $value); } } return $query->first(); }
Notice:Will$query->where($key, $value);
Change to$query->orWhere($key, $value);
That's it!
Then you need to register a custom UserProvider:
class AuthServiceProvider extends ServiceProvider { /** * Register any application certification/authorization services. * * @return void */ public function boot() { $this->registerPolicies(); Auth::provider('custom', function ($app, array $config) { // Return the Illuminate\Contracts\Auth\UserProvider instance... return new CustomUserProvider(new BcryptHasher(), config('')); }); } }
Finally, we modify the configuration and get it done:
'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App\Models\User::class, ], 'custom' => [ 'driver' => 'custom', 'model' => App\Models\User::class, ], ],
Change the provider of the web array to the custom registered before
'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'custom', ], 'api' => [ 'driver' => 'passport', 'provider' => 'users', ], ],
Now even if you have multiple fields, it is perfect...
Summarize
The above is the entire content of this article. I hope that the content of this article has certain reference value for everyone's study or work. If you have any questions, you can leave a message to communicate. Thank you for your support.