Laravel Auth:: attempt () возвращает false
Я домашний любитель и изучаю фреймворк Laravel, в настоящее время в версии 5.3. Я использую Mac, ни homestead, ни vagrant.
В настоящее время я работаю на веб-сайте, который использует систему регистрации и регистрации для создания пользователей.
Я использовал php artisan migrate для локального управления базой данных.
Как указано ниже, он имеет три поля, а именно:
- электронная почта
- имя пользователя
- пароль
У меня есть модель User (пользователи.php):
<?php
namespace blog;
use IlluminateNotificationsNotifiable;
use IlluminateDatabaseEloquentModel;
use IlluminateContractsAuthAuthenticatable;
class User extends Model implements Authenticatable {
use IlluminateAuthAuthenticatable;
use Notifiable;
protected $fillable = [
'username', 'email', 'password',
];
}
А также класс UserController (UserController.php):
<?php
namespace blogHttpControllers;
use Auth;
use blogUser;
use IlluminateHttpRequest;
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';
}
}
?>
Как вы можете видеть, я использую
bcrypt() в качестве метода хэширования.Тем не менее, эта проблема есть, она всегда приведет к неудаче.
Я проверил следующие ссылки:
P.S. эти ссылки кажется, очень трудно следовать, так как я не использую класс Input.
3 ответов:
Проблема заключается в том, как вы перенаправляете пользователя на маршрут
loginпосле регистрации. Вы ошибочно предполагаете, что данные$requestбудут сопровождаться перенаправлением.Предположим такой сценарий: запрос отправляется в метод
postRegisterс помощьюname,passwordполя. Контроллер создает пользователя и сохраняет его в базе данных. Затем он перенаправляет пользователя, который еще не прошел проверку подлинности, на маршрутlogin. МетодpostLoginзапускается, но это время без запроса данных. В результатеAuth::attempt($credentials)терпит неудачу, и вы получаете этот неприятныйFailureна экране.Если вы добавите
dd($credentials)сразу после создания массива, вы увидите, что он не имеет значений: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'; }Он вернет что-то вроде этого:
array:2 [ "username" => null "password" => null ]Вы не можете перенаправить данные пользовательского запроса (за исключением строки запроса, которая является частью URL-адреса), независимо от того, что. Это не то, как работает HTTP. Запрос данных в сторону, вы даже не можете перенаправить с помощью пользовательских заголовков .
Теперь, когда вы знаете, в чем корень вашей проблемы, давайте посмотрим, какие есть варианты ее решения.1. Перенаправление со вспышкой данных
В случае, если вы хотите сохранить эту структуру, вам нужно вставить данные запроса
postRegister()в сеанс (который является постоянным между запросами), а затем извлечь его в методеpostLogin(), используяSessionфасад,session()помощник или фактическийIlluminate\Session\SessionManagerкласс.Вот что я имею в виду:
(я немного изменил ваш код; отбросил дополнительные переменные, сделал его немного чище и т. д.)Я настоятельно рекомендую вам не использовать этот подход. Таким образом, реализация метода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'; }postLogin(), который должен отвечать за вход пользователей, соединяется с данными сеанса, что не очень хорошо. Таким образом, вы не сможете использоватьpostLoginнезависимо отpostRegister.2. Войдите в систему пользователя сразу после регистрации
Это немного лучшее решение; если вы решили, что вам нужно войти в пользователя сразу после регистрации, почему бы просто не сделать это?
Обратите внимание, что собственный контроллер аутентификации Laravel делает это автоматически. Кстати, вот что я имею в виду.:
( В идеале это должно быть разбито на несколько методов, как и собственный контроллер аутентификации Laravel. Но это всего лишь пример для начала.)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(); }Но все же, это далеко не идеально! Есть много других способов решить эту проблему. Один возможно использование событий , выбрасывание исключений при сбое и перенаправление с использованием пользовательских исключений. Но я не собираюсь исследовать их, поскольку уже есть решение, идеально разработанное для этого.
Если вы хотите написать свой собственный контроллер аутентификации, это нормально. Ты многому научишься на этом пути. Но я настоятельно рекомендую прочитать собственный идентификационный код Ларавеля, особенно
RegistersUsersи ещеAuthenticatesUsersчерты характера для того, чтобы учиться от него.И еще одно замечание; вам не нужна эта
Illuminate\Auth\Authenticatableчерта в вашейUserмодели, поскольку она уже расширяетсяAuthenticatableкоторые используют эту черту.
Вы должны хэшировать свой пароль каждый раз, когда вставляете строку bcrypt (pass). Auth:: попытка предполагает, что пароль, получаемый из базы данных, хэшируется
Auth::attemptиспользует\Hash::make($someString)для генерации хэша. Вы должны использовать это также для того, чтобы генерировать те же хэши из тех же строк (я предполагаю, что семя отличается от функцииbcrypt()).Поэтому измените эту строку:
$password = bcrypt($request['password']);Кому:
$password = \Hash::make($request['password']);
Comments