我是家庭爱好者,正在学习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()
作为哈希方法。
然而,问题是,它总会导致失败。
我检查了以下链接:
P.S。这些链接似乎很难遵循,因为我没有使用Input
类。
答案 0 :(得分:4)
问题在于您在注册后将用户重定向到login
路由的方式。您错误地认为$request
数据会伴随重定向。
让我们假设这种情况:使用postRegister
,name
和email
字段将请求分派到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。
现在您知道问题的根源了,让我们看看有哪些方法可以解决问题。
如果要保留此结构,则需要将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
。
这是一个稍好的解决方案;如果您决定在注册后立即登录用户,为什么不这样做呢?
请注意Laravel自己的身份验证控制器does it automatically。
顺便说一句,这就是我的意思:
(理想情况下,这应该分解为多种方法,就像Laravel自己的身份验证控制器一样。但它只是一个让你入门的例子。)
postRegister
但是,它仍然远非完美!还有很多其他方法可以解决这个问题。一个人可能正在使用events,在失败时抛出exceptions并redirecting using custom exceptions。但我不会因为已经a solution perfectly designed for this而探索它们。
如果您想编写自己的身份验证控制器,那很好。在此过程中,您将学到很多东西。但我强烈建议阅读Laravel自己的身份验证代码,尤其是RegistersUsers
和AuthenticatesUsers
特征,以便从中学习。
再说一遍;您不需要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']);