web-dev-qa-db-fra.com

Laravel Auth :: tentative () renvoie false

Je suis un amateur de maison et j'étudie Laravel, actuellement en version 5.3. J'utilise un Mac, ni Homestead ni vagrant

Je travaille actuellement sur un site Web qui utilise un identifiant et un système de registre pour créer des utilisateurs.

J'ai utilisé php artisan migrate pour manipuler ma base de données localement.

 Screen Shot 2016-12-27 at 4.18.38 PM.png

Comme indiqué ci-dessous, il comporte trois champs, à savoir:

  • Email
  • Username
  • Mot de passe

J'ai un modèle User (users.php):

<?php

namespace blog;

use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Contracts\Auth\Authenticatable;

class User extends Model implements Authenticatable {
    use \Illuminate\Auth\Authenticatable;

    use Notifiable;

    protected $fillable = [
        'username', 'email', 'password',
    ];

}

Et aussi, une classe UserController (UserController.php): 

<?php

namespace blog\Http\Controllers;

use Auth;
use blog\User;
use Illuminate\Http\Request;

class UserController extends Controller {

    public function postRegister(Request $request) {
        $username = $request['username'];
        $email = $request['email'];
        $password = bcrypt($request['password']);

        $user = new User();
        $user->email = $email;
        $user->username = $username;
        $user->password = $password;

        $user->save();

        return redirect()->route('login');        
    }

    public function postLogin(Request $request) {

        $credentials = [
            'username' => $request['username'],
            'password' => $request['password'],
        ];

        if(Auth::attempt($credentials)) {
            return redirect()->route('dashboard');       
        }

        return 'Failure'; 
    }
}

?>

Comme vous pouvez le constater, j’utilise bcrypt() comme méthode de hachage.

Cependant, ce problème est, il aboutira toujours à un échec.

 Screen Shot 2016-12-27 at 4.41.38 PM.png

J'ai vérifié les liens suivants:

P.S. Ces liens semblent très difficiles à suivre car je n’utilise pas la classe Input.

5
Programming_Duders

Le problème réside dans la façon dont vous redirigez l'utilisateur vers la route login après l'enregistrement. Vous supposez faussement que les données $request seront accompagnées de la redirection. 

Supposons ce scénario: une demande est envoyée à la méthode postRegister avec les champs name, email et password. Le contrôleur crée l’utilisateur et l’enregistre dans la base de données. Ensuite, il redirige l'utilisateur, qui n'est pas encore authentifié, vers la route login. La méthode postLogin est déclenchée, mais cette fois sans données de demande. En conséquence, Auth::attempt($credentials) échoue et vous obtenez cette Failure désagréable à l'écran. 

Si vous ajoutez un dd($credentials) juste après avoir créé le tableau, vous verrez qu'il n'a pas de valeur: 

public function postLogin(Request $request)
{
    $credentials = [
        'username' => $request['username'],
        'password' => $request['password'],
    ];

    // Dump data
    dd($credentials);

    if (Auth::attempt($credentials)) {
        return redirect()->route('dashboard');
    }

    return 'Failure';
}

Il va retourner quelque chose comme ça: 

array:2 [
  "username" => null
  "password" => null
]

Vous ne pouvez pas rediriger avec des données de demande personnalisées (sauf avec une chaîne de requête qui fait partie de l'URL), peu importe quoi. Ce n'est pas comme ça que HTTP fonctionne. Demander des données de côté, vous ne pouvez même pas rediriger avec des en-têtes personnalisés

Maintenant que vous savez quelle est la racine de votre problème, voyons quelles sont les options pour le résoudre. 

1. Redirection avec des données flashées

Si vous souhaitez conserver cette structure, vous devez flasher les données de requête de postRegister() dans la session (qui est persistante entre les requêtes), puis les extraire dans la méthode postLogin() à l'aide de Session facade, de session() helper ou de la classe Illuminate\Session\SessionManager réelle. 

Voici ce que je veux dire:
(J'ai légèrement modifié votre code; j'ai laissé tomber des variables supplémentaires, je l'ai rendu un peu plus propre, etc.)

public function postRegister(Request $request)
{
    // Retrieve all request data including username, email & password.
    // I assume that the data IS validated.
    $input = $request->all();

    // Hash the password
    $input['password'] = bcrypt($input['password']);

    // Create the user
    User::create($input);

    // Redirect
    return redirect()
        // To the route named `login`
        ->route('login')

        // And flash the request data into the session,
        // if you flash the `$input` into the session, you'll
        // get a "Failure" message again. That's because the 
        // password in the $input array is already hashed and 
        // the attempt() method requires user's password, not 
        // the hashed copy of it. 
        //
        ->with($request->only('username', 'password'));
}

public function postLogin(Request $request)
{
    // Create the array using the values from the session
    $credentials = [
        'username' => session('username'),
        'password' => session('password'),
    ];

    // Attempt to login the user
    if (Auth::attempt($credentials)) {
        return redirect()->route('dashboard');
    }

    return 'Failure';
}

Je vous recommande fortement de ne pas utiliser cette approche. De cette façon, la mise en œuvre de la méthode postLogin() qui est supposée être responsable de la connexion des utilisateurs est couplée avec des données de session qui ne sont pas bonnes. De cette façon, vous ne pouvez pas utiliser postLogin indépendamment de postRegister.

2. Connectez-vous l'utilisateur juste après l'enregistrement

C'est une solution légèrement meilleure. Si vous avez décidé de vous connecter après l’enregistrement, pourquoi ne pas le faire? 

Notez que le propre contrôleur d’authentification de Laravel le fait automatiquement

Au fait, voici ce que je veux dire:
(Idéalement, cela devrait être divisé en plusieurs méthodes, tout comme le propre contrôleur d’authentification de Laravel. Mais c’est juste un exemple pour vous aider à démarrer.)} _

public function postRegister(Request $request)
{
    $input = $request->all();

    $input['password'] = bcrypt($input['password']);

    User::create($input);

    // event(UserWasCreated::class);

    if (Auth::attempt($request->only('username', 'password'))) {
        return redirect()
            ->route('dashboard')
            ->with('Welcome! Your account has been successfully created!');
    }

    // Redirect
    return redirect()
        // To the previous page (probably the one generated by a `getRegister` method)
        ->back()
        // And with the input data (so that the form will get populated again)
        ->withInput();
}

Mais quand même, c'est loin d'être parfait! Il existe de nombreuses autres manières de s’y attaquer. On pourrait utiliser events , lancer exceptions en cas d'échec et rediriger à l'aide d'exceptions personnalisées . Mais je ne vais pas les explorer car il y a déjà une solution parfaitement conçue pour cela

Si vous voulez écrire votre propre contrôleur d'authentification, c'est très bien. Vous apprendrez beaucoup en cours de route. Mais je suggère fortement de lire le code d'authentification de Laravel, en particulier RegistersUsers et AuthenticatesUsers traits pour en tirer des enseignements. 

Et encore une note; vous n'avez pas besoin de ce trait Illuminate\Auth\Authenticatable dans votre modèle User car il s'étend déjà/ Authenticatable qui utilise ce trait.

3
sepehr

Vous devez hacher votre mot de passe chaque fois que vous insérez une ligne bcrypt (pass). Auth :: tentative suppose que le mot de passe extrait de la base de données est haché

1
vachina