我是一名家庭爱好者,正在学习 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()
作为我的散列方法。
但是,这个问题是,它总是会导致失败。
我检查了以下链接:
PS 这些链接似乎很难理解,因为我没有使用 Input
类。
原文由 Programming_Duders 发布,翻译遵循 CC BY-SA 4.0 许可协议
问题在于您在注册后将用户重定向到
login
路由的方式。您错误地假设$request
数据将伴随重定向。Let’s assume this scenario: A request gets dispatched to the
postRegister
method withname
,email
andpassword
fields.控制器创建用户并将其保存到数据库中。然后它将尚未通过身份验证的用户重定向到login
路由。postLogin
方法被触发,但这次没有请求数据。结果,Auth::attempt($credentials)
失败了,你会在屏幕上看到讨厌的Failure
。如果您在创建数组后立即添加
dd($credentials)
,您会看到它没有值:它将返回如下内容:
无论如何,您都无法使用自定义请求数据进行重定向(除非使用作为 URL 一部分的查询字符串)。这不是 HTTP 的工作方式。除了请求数据, 您甚至无法使用自定义标头重定向。
现在您知道问题的根源是什么,让我们看看有哪些解决方法。
1. 使用闪存数据重定向
如果要保留此结构,则需要将
postRegister()
的请求数据闪存到会话中(在请求之间是持久的),然后在postLogin()
方法中使用Session
外观,session()
助手或实际Illuminate\Session\SessionManager
类。这就是我的意思:
( 我稍微修改了您的代码;删除了额外的变量,使其更简洁,等等。 )
我强烈建议您不要使用这种方法。这样,应该负责登录用户的
postLogin()
方法的实现与不好的会话数据相结合。这样,您将无法独立于 --- 使用postLogin
postRegister
。2.注册后立即登录用户
这是一个稍微好一点的解决方案;如果您决定在注册后立即登录用户,为什么不这样做呢?
请注意,Laravel 自己的身份验证控制器 会自动执行此操作。
顺便说一句,这就是我的意思:
(理想情况下,这应该分解为多种方法,就像 Laravel 自己的身份验证控制器一样。但这只是一个让您入门的示例。)
但是,它仍然 远非完美!还有很多其他方法可以解决这个问题。一种可能是使用 事件,在失败时抛出 异常 并 使用自定义异常进行重定向。但我不打算探索它们,因为已经 有一个完美设计的解决方案。
如果您想编写自己的身份验证控制器,那很好。一路上你会学到很多东西。但我强烈建议阅读 Laravel 自己的验证码,尤其是
RegistersUsers
和AuthenticatesUsers
特征,以便从中学习。还有一个注意事项;您不需要
Illuminate\Auth\Authenticatable
您的User
模型中的特征,因为它已经在扩展Authenticatable
使用该特征。