我是一个家庭爱好者,正在学习拉威尔,目前在版本5.3.我用的是Mac电脑,既不是homestead也不是vagrant.

我目前正在开发一个网站,使用登录和注册系统创建用户.

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

Screen Shot 2016-12-27 at 4.18.38 PM.png

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

  • 邮箱
  • 用户名
  • Password

我有一个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()作为哈希方法.

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

Screen Shot 2016-12-27 at 4.41.38 PM.png

我已经判断了以下链接:

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

推荐答案

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

让我们假设这样的场景:一个请求被分派到具有nameemailpassword字段的postRegister方法.控制器创建用户并将其保存到数据库中.则它将尚未认证的用户重定向到login路由.postLogin方法被触发,但这一次没有请求数据.结果,Auth::attempt($credentials)失败了,你会在屏幕上看到令人讨厌的Failure.

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

It will return something like this:

array:2 [
  "username" => null
  "password" => null
]

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.

既然你知道问题的根源是什么,让我们看看有什么办法可以解决它.

1.使用闪存数据重定向

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

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.

2. Login the user right after the registration

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?

Note that Laravel's own authentication controller does it automatically.

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();
}

但仍然是far from perfect!还有很多其他方法可以解决这个问题.其中一个可能使用events,失败时投掷exceptions,失败时投掷a solution perfectly designed for this197/65732">redirecting using custom exceptions.但我不会go 探索它们,因为已经有a solution perfectly designed for this个了.

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.

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相关问答推荐

运行NPM Prod时出现VUE问题

如何定制有关密码被泄露的Laravel Breeze S消息?

Laravel Eloquent查询与集合优化

如何从laravel中的另一个表中获取用户名

如何在 Laravel 中使用 Vue 路由?

前端和管理员分开时未加载laravel 9中间件

如何通过一个 laravel 安装处理子域

我怎样才能了解更多关于我的 Laravel 排队作业(job)失败的原因?

升级到 laravel 5.4 后调用未定义的方法

SQLSTATE [42000]:语法错误或访问冲突:1066 Not unique table/alias on relationship

向 Docker 上的 Artisan 推荐方式

Laravel Eloquent 模型中的字段

使用 Laravel 创建新项目会引发异常

升级到 laravel 5.3 后错误 datetime format: 1292 Incorrect datetime value: '0000-00-00 00:00:00'

Laravel 表:只能有一个自动列,并且必须定义为键

Laravel 5 事件处理程序未触发

如何在 vs 代码中自动导入 laravel 类

如何在 Laravel 测试中禁用选定的中间件

Laravel 4 - 文件上传

如何在脚本文件中使用 Laravel Blade?