Laravel Auth :: attempt()返回false

时间:2016-12-27 09:56:52

标签: php laravel authentication laravel-5.3

我是家庭爱好者,正在学习Laravel,目前版本为5.3。我使用的是Mac,homesteadvagrant

我目前正在使用登录系统和注册系统创建用户的网站上工作。

我已使用php artisan migrate在本地操作我的数据库。

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

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

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

我有一个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',
    ];

}

还有一个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'; 
    }
}

?>

如您所见,我使用bcrypt()作为哈希方法。

然而,问题是,它总会导致失败。

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

我检查了以下链接:

P.S。这些链接似乎很难遵循,因为我没有使用Input类。

3 个答案:

答案 0 :(得分:4)

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

让我们假设这种情况:使用postRegisternameemail字段将请求分派到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的工作方式。请求数据,you can't even redirect with custom headers

现在您知道问题的根源了,让我们看看有哪些方法可以解决问题。

1。使用闪烁数据重定向

如果要保留此结构,则需要将postRegister()的请求数据刷新到会话中(在请求之间保持不变),然后使用{{postLogin()方法检索它。 1}} facade,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

2。注册后立即登录用户

这是一个稍好的解决方案;如果您决定在注册后立即登录用户,为什么不这样做呢?

请注意Laravel自己的身份验证控制器does it automatically

顺便说一句,这就是我的意思:
(理想情况下,这应该分解为多种方法,就像Laravel自己的身份验证控制器一样。但它只是一个让你入门的例子。)

postRegister

但是,它仍然远非完美!还有很多其他方法可以解决这个问题。一个人可能正在使用events,在失败时抛出exceptionsredirecting using custom exceptions。但我不会因为已经a solution perfectly designed for this而探索它们。

如果您想编写自己的身份验证控制器,那很好。在此过程中,您将学到很多东西。但我强烈建议阅读Laravel自己的身份验证代码,尤其是RegistersUsersAuthenticatesUsers特征,以便从中学习。

再说一遍;您不需要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(); } 模型中的Illuminate\Auth\Authenticatable特征,因为它已经扩展了使用该特征的Authenticatable

答案 1 :(得分:1)

每次插入行bcrypt(pass)时都应该对密码进行哈希处理。 Auth :: attempt假定从数据库中检索的密码是经过哈希处理的

答案 2 :(得分:-2)

Auth::attempt使用\Hash::make($someString)生成哈希。您也应该使用它来从相同的字符串生成相同的哈希值(我假设种子与bcrypt()函数不同)。

所以改变这一行:

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

要:

$password = \Hash::make($request['password']);