Laravel Auth::attempt() 返回 false
Posted
技术标签:
【中文标题】Laravel Auth::attempt() 返回 false【英文标题】:Laravel Auth::attempt() returns false 【发布时间】:2017-05-11 14:33:54 【问题描述】:我是一名家庭爱好者,正在学习 Laravel,目前版本为5.3
。我使用的是 Mac,既不是 homestead
也不是 vagrant
。
我目前正在开发一个使用登录和注册系统来创建用户的网站。
我使用php artisan migrate
在本地操作我的数据库。
如下所列,它有三个字段,分别是:
电子邮件 用户名 密码我有一个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()
作为我的哈希方法。
但是,这个问题,总是会导致失败。
我已经检查了以下链接:
Why is Auth::attempt always returns false
Laravel authattempt return false
附:由于我没有使用 Input
类,因此这些链接似乎很难理解。
【问题讨论】:
Laravel 自带 authentication controller。为什么不使用它而不是自己编写? 您的“登录”路线是使用 GET 方法吗?你能附上你的路线吗? 【参考方案1】:问题在于您在注册后将用户重定向到login
路由的方式。您错误地假设 $request
数据将伴随重定向。
让我们假设这种情况:一个请求被分派到具有name
、email
和password
字段的postRegister
方法。控制器创建用户并将其保存到数据库中。然后它将尚未通过身份验证的用户重定向到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()
方法中使用Session
门面,@ 987654346@ 助手或实际的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()
方法的实现与不好的会话数据相结合。这样一来,您就无法独立于 postRegister
使用 postLogin
。
2。注册后立即登录用户
这是一个稍微好一点的解决方案;如果您决定在注册后立即登录用户,为什么不这样做呢?
请注意 Laravel 自己的身份验证控制器 does it automatically。
顺便说一句,我的意思是:(理想情况下,这应该分解成多个方法,就像 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();
但是,它仍然远非完美!还有很多其他方法可以解决这个问题。一种可能是使用events,在失败时抛出exceptions 和redirecting using custom exceptions。但我不会去探索它们,因为已经有a solution perfectly designed for this。
如果您想编写自己的身份验证控制器,那很好。一路上你会学到很多东西。但我强烈建议阅读 Laravel 自己的认证代码,尤其是 RegistersUsers
和 AuthenticatesUsers
特征以便从中学习。
还有一个注意事项;您不需要 Illuminate\Auth\Authenticatable
模型中的 Illuminate\Auth\Authenticatable
特征,因为它已经扩展了使用该特征的 Authenticatable
。
【讨论】:
非常感谢您所做的一切,尽管解决方案 1 的结果并不是那么好,而且解决方案 2 遇到了很多错误... :( 不客气。您遇到了什么类型的错误? 我仍然得到解决方案 1 的“失败”(闪烁),并且当我执行“dd”凭据时,它正在为 postRegister() 工作,但当我在 postLogin() 中执行它时变为 null 太棒了! :) 你是对的;第一个解决方案的代码存在问题,我修复了它并解释了代码 cmets 的问题。请再次测试。第二个工作得很好。关于dd
的事情,这是预期的行为; postLogin
中没有请求数据,所以都是null
。我在答案中解释了原因。【参考方案2】:
您应该在每次插入一行 bcrypt(pass) 时散列您的密码。 Auth::attempt 假定从数据库中检索的密码是经过哈希处理的
【讨论】:
【参考方案3】:Auth::attempt
使用\Hash::make($someString)
生成哈希。您也应该使用它来从相同的字符串生成相同的哈希(我假设种子与 bcrypt()
函数不同)。
所以改变这一行:
$password = bcrypt($request['password']);
收件人:
$password = \Hash::make($request['password']);
【讨论】:
这太棒了,但它仍然没有解决我的问题,遗憾的是...... :( 嗯,你有没有尝试在更改代码后创建新用户?您确定用户正在保存到数据库中吗? 是的,我有。用户保存在数据库中,我将在上面的问题中发布更新... :) 两者都是一样的。bcrypt
function 只是相同功能的助手。
哦,好吧。然后我不知道它可能是什么。以上是关于Laravel Auth::attempt() 返回 false的主要内容,如果未能解决你的问题,请参考以下文章
在 Auth::attempt() Laravel 5.1 中禁用重定向
Laravel Auth::attempt() 可以处理关系吗?
Laravel 5 Auth::attempt() 总是返回 false
Laravel 4 Auth::attempt() 总是返回 false