[英]Laravel Auth::attempt() returns false
我是一名家庭愛好者,正在學習 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
類。
問題在於您在login
后將用戶重定向到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的工作原理。 除了請求數據之外, 您甚至無法使用自定義標頭重定向 。
既然您知道問題的根源是什么,那么讓我們看看有哪些方法可以解決它。
如果你想保留這個結構,你需要將postRegister()
的請求數據閃存到會話中(在請求之間是持久的),然后使用Session
facade, session()
helper或者postLogin()
方法檢索它。實際的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()
會話數據相結合。 這樣,您就無法獨立於postRegister
使用postLogin
。
這是一個稍好的解決方案; 如果您決定在注冊后立即登錄用戶,為什么不這樣做呢?
請注意,Laravel自己的身份驗證控制器會自動執行此操作 。
順便說一句,這就是我的意思:
(理想情況下,這應該分解為多種方法,就像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();
}
但是,它還遠非完美 ! 還有很多其他方法可以解決這個問題。 一個可能是使用事件 ,在失敗時拋出異常並使用自定義異常重定向 。 但是我不會去探索它們,因為已經有一個完美的解決方案 。
如果你想編寫自己的身份驗證控制器,那很好。 在此過程中你會學到很多東西。 但我強烈建議閱讀Laravel自己的身份驗證代碼,尤其是RegistersUsers
和AuthenticatesUsers
特性,以便從中學習。
再說一遍; 您在User
模型中不需要Illuminate\\Auth\\Authenticatable
特征,因為它已經擴展了使用該特征的Authenticatable
。
每次插入行bcrypt(pass)時都應該對密碼進行哈希處理。 Auth :: attempt假定從數據庫中檢索的密碼是經過哈希處理的
請問你能給我解決方案嗎? 我在這里有同樣的問題
" Auth::attempt
使用\\Hash::make($someString)
來生成哈希。 您也應該使用它來從相同的字符串生成相同的哈希值(我假設種子與bcrypt()
函數不同)。
所以改變這一行:
$password = bcrypt($request['password']);
至:
$password = \Hash::make($request['password']);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.