簡體   English   中英

Laravel Auth::attempt() 返回 false

[英]Laravel Auth::attempt() returns false

我是一名家庭愛好者,正在學習 Laravel,目前版本5.3 我使用的是 Mac,既不是homestead也不是vagrant

我目前正在開發一個使用登錄和注冊系統來創建用戶的網站。

我使用php artisan migrate在本地操作我的數據庫。

屏幕截圖 2016 年 12 月 27 日下午 4.18.38.png

如下所列,它具有三個字段,即:

  • 電子郵件
  • 用戶名
  • 密碼

我有一個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()作為我的散列方法。

但是,這個問題是,它總是會導致失敗。

屏幕截圖 2016 年 12 月 27 日下午 4.41.38.png

我檢查了以下鏈接:

PS 這些鏈接似乎很難理解,因為我沒有使用Input類。

問題在於您在login后將用戶重定向到login路由的方式。 您錯誤地假設$request數據將伴隨重定向。

讓我們假設這種情況:使用nameemailpassword字段將請求分派到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的工作原理。 除了請求數據之外, 您甚至無法使用自定義標頭重定向

既然您知道問題的根源是什么,那么讓我們看看有哪些方法可以解決它。

1.使用閃爍數據重定向

如果你想保留這個結構,你需要將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

2.注冊后立即登錄用戶

這是一個稍好的解決方案; 如果您決定在注冊后立即登錄用戶,為什么不這樣做呢?

請注意,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自己的身份驗證代碼,尤其是RegistersUsersAuthenticatesUsers特性,以便從中學習。

再說一遍; 您在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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM