简体   繁体   中英

Why Laravel Auth::guard()->attempt() isn't working?

So basically I generate users data after a payment, which it is saved in a table I created, it has a username and a encrypted password with Hash::make() method.

What I wanna do is to login with that data stored in the DB, so I made a guard.

This is the auth.php file with guards:

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],
    'plataforma' => [
        'driver' => 'session',
        'provider' => 'usuario',
    ],
],

And these are the providers:

'providers' => [
    'users' => [
        'driver' => 'eloquent',
        'model' => App\Models\User::class,
    ],
    'usuario' => [
        'driver' => 'eloquent',
        'model' => App\Models\Usuario::class,
    ],

This is the model:

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;


class Usuario extends Authenticatable
{
    use HasFactory;
    use Notifiable;

    protected $guard = 'plataforma';

    protected $fillable = [
        'nombre_usuario', 'correo', 'clave',
    ];

    protected $hidden = [
        'clave', 'remember_token',
    ];
}

And finally the controller:

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;

class PlataformaController extends Controller
{
    public function login()
    {
        return view('web.plataforma-login');
    }

    public function autenticar(Request $request)
    {
        if (Auth::guard('plataforma')->attempt(['nombre_usuario' => $request->input('nombre_usuario'), 'clave' => $request->input('clave')])) {
            return view('web.plataforma');
        } else {
            dd(Auth::guard('plataforma')->attempt(['nombre_usuario' => $request->input('nombre_usuario'), 'clave' => $request->input('clave')]));
        }
    }

    public function dashboard()
    {
        return view('web.plataforma');
    }
}

So basically the Auth::guard('plataforma')->attempt(...) returns false, I already checked that the values of $request->input(...) are correct, I checked that the encrypted password in the DB is the same as the password that the user enter with Hash::check(), so I don't know what is wrong and I'm so confused...

I spent a lot of time reading other questions with no solutions either, I would be glad if anyone can help me out.

After reading the API, I've come to the conclusion attempt() is not working to you because you're using a different password column name.

The following is the attempt function's code from the Illuminate\Auth\SessionGuard class:

 /** * Attempt to authenticate a user using the given credentials. * * @param array $credentials * @param bool $remember * @return bool */ public function attempt(array $credentials = [], $remember = false) { $this->fireAttemptEvent($credentials, $remember); $this->lastAttempted = $user = $this->provider->retrieveByCredentials($credentials); // If an implementation of UserInterface was returned, we'll ask the provider // to validate the user against the given credentials, and if they are in // fact valid we'll log the users into the application and return true. if ($this->hasValidCredentials($user, $credentials)) { $this->login($user, $remember); return true; } // If the authentication attempt fails we will fire an event so that the user // may be notified of any suspicious attempts to access their account from // an unrecognized user. A developer may listen to this event as needed. $this->fireFailedEvent($user, $credentials); return false; }

The key functions here are retrieveByCredentials and hasValidCredentials

Here's retrieveByCredentials from Illuminate\Auth\EloquentUserProvider . As you can see, it's excluding the 'password' key from the query in the foreach.

 /** * Retrieve a user by the given credentials. * * @param array $credentials * @return \Illuminate\Contracts\Auth\Authenticatable|null */ public function retrieveByCredentials(array $credentials) { if (empty($credentials) || (count($credentials) === 1 && → Str::contains($this->firstCredentialKey($credentials), 'password'))) { ← 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->newModelQuery(); foreach ($credentials as $key => $value) { → if (Str::contains($key, 'password')) { ← continue; } if (is_array($value) || $value instanceof Arrayable) { $query->whereIn($key, $value); } elseif ($value instanceof Closure) { $value($query); } else { $query->where($key, $value); } } return $query->first(); }

Here's hasValidCredentials from Illuminate\Auth\EloquentUserProvider . The key function here is validateCredentials

 /** * Determine if the user matches the credentials. * * @param mixed $user * @param array $credentials * @return bool */ protected function hasValidCredentials($user, $credentials) { $validated =, is_null($user) && $this->provider->validateCredentials($user; $credentials); if ($validated) { $this->fireValidatedEvent($user); } return $validated; }

Here's validateCredentials from the Illuminate\Auth\EloquentUserProvider class. You can see it's again, using by default 'password' as the key name. Let's see what getAuthPassword() looks like.

 /** * 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()); }

And finally getAuthPassword from the Illuminate\Auth\Authenticatable class. It's just returning the model's 'password' attribute.

 /** * Get the password for the user. * * @return string */ public function getAuthPassword() { → return $this->password; ← }



Basically, if you want this to work, you need to change a few things about your code.

  1. Use password as the key in attempt()
public function autenticar(Request $request)
{
    $attempt = Auth::guard('plataforma')->attempt([
        'nombre_usuario' => $request->input('nombre_usuario'),
        'password' => $request->input('clave')
    ]);

    if ($attempt) {
        return view('web.plataforma');
    } else {
        dd($attempt);
    }
}
  1. Override your Authenticatable model (Usuario)'s getAuthPassword method.
# Usuario model
/**
 * Get the password for the user.
 *
 * @return string
 */
public function getAuthPassword()
{
    return $this->clave;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM