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.
Comme indiqué ci-dessous, il comporte trois champs, à savoir:
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.
J'ai vérifié les liens suivants:
P.S. Ces liens semblent très difficiles à suivre car je n’utilise pas la classe Input
.
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.
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
.
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.
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é