Laravel Auth::attempt() 返回 false

2022-08-30 23:39:25

我是一个家庭爱好者,正在学习Laravel,目前在版本中。我使用的是 Mac,既不是,也不是 .5.3homesteadvagrant

我目前正在开发一个使用登录和注册系统来创建用户的网站。

我曾经在本地操作我的数据库。php artisan migrate

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

如下所列,它有三个字段,即:

  • 电子邮件
  • 用户名
  • 密码

我有一个模型(用户.php):User

<?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',
    ];

}

还有一个类(用户控制器.php):UserController

<?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'; 
    }
}

?>

如您所见,我正在使用我的哈希方法。bcrypt()

但是,这个问题是,它总是会导致失败。

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

我检查了以下链接:

附言:这些链接似乎很难遵循,因为我没有使用该类。Input


答案 1

问题在于您在注册后将用户重定向到路由的方式。您错误地认为数据将伴随重定向一起出现。login$request

假设场景:将请求分派到具有 和 字段的方法。控制器创建用户并将其保存到数据库中。然后,它将尚未通过身份验证的用户重定向到路由。该方法被触发,但这次没有请求数据。结果,失败,你在屏幕上变得讨厌。postRegisternameemailpasswordloginpostLoginAuth::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()Sessionsession()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()postLoginpostRegister

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

但是,它仍然远非完美!还有许多其他方法可以解决这个问题。一种可能是使用事件,在失败时引发异常,并使用自定义异常进行重定向。但我不打算探索它们,因为已经有一个完美的解决方案。

如果要编写自己的身份验证控制器,那很好。一路走来,你会学到很多东西。但我强烈建议阅读Laravel自己的身份验证代码,特别是RegistersUsersAuthorationsUsers特征,以便从中学习。

还有一个注意事项;你的模型中不需要这个特征,因为它已经扩展了使用该特征的AuthentialatableIlluminate\Auth\AuthenticatableUser


答案 2

您应该在每次插入行bcrypt(pass)时对密码进行哈希处理。Auth::尝试假定从数据库中检索到的密码已进行哈希处理


推荐