php Laravel Auth::attempt() 返回 false
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/41342907/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Laravel Auth::attempt() returns false
提问by Programming_Duders
I am a home hobbyist and am studying Laravel, currently in version 5.3
. I am using a Mac, neither homestead
nor vagrant
.
我是一个家庭爱好者,正在学习 Laravel,目前在5.3
. 我使用的是 Mac,既不homestead
是vagrant
.
I'm currently working on a website that uses a login and a register system to create users.
我目前正在开发一个使用登录名和注册系统来创建用户的网站。
I've used php artisan migrate
to manipulate my database locally.
我曾经php artisan migrate
在本地操作我的数据库。
As listed below, it has three fields, namely:
如下所示,它包含三个字段,即:
- Username
- Password
- 电子邮件
- 用户名
- 密码
I have a User
model (users.php):
我有一个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',
];
}
And also, a UserController
class (UserController.php):
还有一个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';
}
}
?>
As you can see, I am using bcrypt()
as my hashing method.
如您所见,我正在使用bcrypt()
我的散列方法。
However, this problem is, it will always result to a failure.
然而,这个问题是,它总是会导致失败。
I have checked the following links:
我检查了以下链接:
P.S. These links seem very hard to follow as I do not utilize the Input
class.
PS 这些链接似乎很难遵循,因为我不使用Input
该类。
采纳答案by sepehr
The problem is with the way you're redirecting the user to login
route after the registration. You're falsely assuming that the $request
data will be accompanied with the redirect.
问题在于您在login
注册后将用户重定向到路由的方式。您错误地假设$request
数据将伴随重定向。
Let's assume this scenario: A request gets dispatched to the postRegister
method with name
, email
and password
fields. The controller creates the user and saves it into the database. Then it redirects the user, who is not yet authenticated, to the login
route. The postLogin
method gets triggered, but this time with no request data. As a result, Auth::attempt($credentials)
fails and you get that nasty Failure
on screen.
让我们假设这个场景:一个请求被分派到postRegister
带有name
、email
和password
字段的方法。控制器创建用户并将其保存到数据库中。然后它将尚未通过身份验证的用户重定向到该login
路由。该postLogin
方法被触发,但这次没有请求数据。结果,Auth::attempt($credentials)
失败了,你会Failure
在屏幕上变得讨厌。
If you add a dd($credentials)
right after you create the array, you'll see that it has no values:
如果dd($credentials)
在创建数组后添加一个right,您将看到它没有值:
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';
}
It will return something like this:
它将返回如下内容:
array:2 [
"username" => null
"password" => null
]
You cannot redirect with custom request data (unless with querystring which is part of the URL), not matter what. It's not how HTTP works. Request data aside, you can't even redirect with custom headers.
您不能使用自定义请求数据重定向(除非使用作为 URL 一部分的查询字符串),无论怎样。这不是 HTTP 的工作方式。除了请求数据之外,您甚至无法使用自定义标头重定向。
Now that you know what's the root of your problem, let's see what are the options to fix it.
现在您知道问题的根源是什么,让我们看看有哪些解决方法。
1. Redirect with flashed data
1. 使用闪存数据重定向
In case you want to preserve this structure, you need to flash the request data of postRegister()
into the session (which is persistent between requests) and then retrieve it in the postLogin()
method using Session
facade, session()
helper or the actual Illuminate\Session\SessionManager
class.
如果您想保留此结构,您需要将请求数据postRegister()
写入会话(在请求之间是持久的),然后在postLogin()
方法中使用Session
Facade、session()
helper 或实际Illuminate\Session\SessionManager
类检索它。
Here's what I mean:
(I slightly modified your code; dropped extra variables, made it a lil bit cleaner, etc.)
这就是我的意思是:
(我稍微修改你的代码;下降的其他变量,使之成为律位清洁器等)
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';
}
I strongly recommend you against using this approach. This way the implementation of postLogin()
method which is supposed to be responsible to login users gets coupled with session data which is not good. This way, you're not able to use postLogin
independently from the postRegister
.
我强烈建议您不要使用这种方法。这样postLogin()
,应该负责登录用户的方法的实现与不好的会话数据耦合。这样,您就无法postLogin
独立于postRegister
.
2. Login the user right after the registration
2. 注册后立即登录用户
This is a slightly better solution; If you decided that you need to log in the user right after the registration, why not just doing that?
这是一个稍微好一点的解决方案;如果您决定需要在注册后立即登录用户,为什么不这样做呢?
Note that Laravel's own authentication controller does it automatically.
请注意,Laravel 自己的身份验证控制器会自动执行此操作。
By the way, here's what I mean:
(Ideally this should be broken down into multiple methods, just like Laravel's own authentication controller. But it's just an example to get you started.)
顺便说一句,这就是我的意思:(
理想情况下,这应该分解为多个方法,就像 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();
}
But still, it's far from perfect! There are many other ways to tackle this. One could be using events, throwing exceptionson failure and redirecting using custom exceptions. But I'm not gonna explore them as there's already a solution perfectly designed for this.
但是,它仍然远非完美!有很多其他方法可以解决这个问题。一种可能是使用事件、在失败时抛出异常和使用自定义异常重定向。但我不会探索它们,因为已经有一个完美的解决方案。
If you want to write your own authentication controller, that's fine. You'll learn a lot along the way. But I strongly suggest reading Laravel's own authentication code, especially RegistersUsers
and AuthenticatesUsers
traits in order to learn from it.
如果您想编写自己的身份验证控制器,那很好。一路上你会学到很多东西。但我强烈建议阅读 Laravel 自己的身份验证代码,特别是RegistersUsers
和AuthenticatesUsers
trait 以便从中学习。
And one more note; you don't need that Illuminate\Auth\Authenticatable
trait in your User
model as it's already extending Authenticatable
which use that trait.
还有一张纸条;您Illuminate\Auth\Authenticatable
的User
模型中不需要该特征,因为它已经在扩展Authenticatable
使用该特征的部分。
回答by vachina
You should hash your password everytime you insert a row bcrypt(pass). Auth::attempt assumes that the password being retrieved from the database is hashed
每次插入一行 bcrypt(pass) 时,您都应该对密码进行哈希处理。Auth::attempt 假设从数据库中检索的密码是经过哈希处理的
回答by DevK
Auth::attempt
uses \Hash::make($someString)
to generate the hash. You should use this as well in order to generate same hashes from same strings (I assume the seed is different than with bcrypt()
function).
Auth::attempt
用于\Hash::make($someString)
生成哈希。您也应该使用它来从相同的字符串生成相同的哈希值(我假设种子与bcrypt()
函数不同)。
So change this line:
所以改变这一行:
$password = bcrypt($request['password']);
To:
到:
$password = \Hash::make($request['password']);