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.

1367   3  

3 ответов:

Проблема заключается в том, как вы перенаправляете пользователя на маршрут loginпосле регистрации. Вы ошибочно предполагаете, что данные $request будут сопровождаться перенаправлением.

Предположим такой сценарий: запрос отправляется в метод postRegister с помощью name, email и 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

    Ничего не найдено.