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

查看:109
本文介绍了Laravel Auth :: attempt()返回false的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是一名家庭爱好者,正在学习Laravel,当前版本为5.3.我正在使用Mac,而不是homesteadvagrant.

I am a home hobbyist and am studying Laravel, currently in version 5.3. I am using a Mac, neither homestead nor vagrant.

我目前正在使用登录和注册系统创建用户的网站上.

I'm currently working on a website that uses a login and a register system to create users.

我已经使用php artisan migrate在本地操作我的数据库.

I've used php artisan migrate to manipulate my database locally.

如下所示,它具有三个字段,即:

As listed below, it has three fields, namely:

  • 电子邮件
  • 用户名
  • 密码

我有一个User模型(users.php):

I have a User model (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):

And also, a UserController class (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()作为我的哈希方法.

As you can see, I am using bcrypt() as my hashing method.

但是,这个问题总是会导致失败.

However, this problem is, it will always result to a failure.

我检查了以下链接:

Laravel authattempt返回false

P.S.这些链接似乎很难遵循,因为我没有使用Input类.

P.S. These links seem very hard to follow as I do not utilize the Input class.

推荐答案

问题在于注册后将用户重定向到login路由的方式.您错误地假设$request数据将伴随重定向.

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.

让我们假设这种情况:使用nameemailpassword字段将请求分派到postRegister方法.控制器创建用户并将其保存到数据库中.然后,它将尚未通过身份验证的用户重定向到login路由. postLogin方法被触发,但是这次没有请求数据.结果,Auth::attempt($credentials)失败,并且您在屏幕上看到该讨厌的Failure.

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.

如果在创建数组后立即添加dd($credentials),则会看到它没有值:

If you add a dd($credentials) right after you create the array, you'll see that it has no values:

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中的querystring进行重定向),无论如何.这不是HTTP的工作方式.除了请求数据之外,您甚至无法使用自定义标头重定向.

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.

现在您知道问题的根源是什么,让我们看看有哪些解决方案.

Now that you know what's the root of your problem, let's see what are the options to fix it.

如果要保留此结构,则需要将postRegister()的请求数据刷新到会话中(在请求之间是持久的),然后使用Session外观在postLogin()方法中检索它们,session()助手或实际的Illuminate\Session\SessionManager类.

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.

这是我的意思:
(我略微修改了您的代码;删除了多余的变量,使其变得有点整洁了,等等.)

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';
}

我强烈建议您不要使用这种方法.这样,应该负责登录用户的postLogin()方法的实现与不好的会话数据结合在一起.这样,您将无法独立于postRegister使用postLogin.

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.

这是一个更好的解决方案;如果您确定需要在注册后立即登录用户,为什么不这样做呢?

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?

请注意,Laravel自己的身份验证控制器自动执行.

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.)

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 exceptions on failure and redirecting using custom exceptions. But I'm not gonna explore them as there's already a solution perfectly designed for this.

如果您想编写自己的身份验证控制器,那很好.您将在此过程中学到很多东西.但我强烈建议阅读Laravel自己的身份验证代码,尤其是 RegistersUsers AuthenticatesUsers 特质,以便从中学习.

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.

还有一个音符;您不需要在User模型中使用Illuminate\Auth\Authenticatable特征,因为它已经扩展了

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.

这篇关于Laravel Auth :: attempt()返回false的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆