3

我想使用 Laravel Fortify 和 Livewire 创建一个非常简单的登录表单。我不想使用 Jetstream,因为它有更多我不需要的功能和我需要的功能。

我在整个应用程序中使用 livewire,并希望将它用于我的登录页面以提供实时即时验证。

我遇到的问题是,如果我wire:model在输入上使用,我无法提交带有值的表单。

我也不能使用auth()->attempt(),因为它被 Fortify 劫持了。(至少,我认为是。众所周知,当我使用它时,它会返回false

如何将 livewire 与 fortify 一起使用?我需要将数据从 livewire 组件发送到POST /login.

这是我目前的设置:

FortifyServiceProvider.php

public function boot()
    {
        Fortify::createUsersUsing(CreateNewUser::class);
        Fortify::updateUserProfileInformationUsing(UpdateUserProfileInformation::class);
        Fortify::updateUserPasswordsUsing(UpdateUserPassword::class);
        Fortify::resetUserPasswordsUsing(ResetUserPassword::class);

        // Custom Fortify Views =============================

        // Login Page
        Fortify::loginView(function () {
            return view('auth.login');
        });
   }

我的auth/login.blade.php(只需使用适当的布局模板调用 livewire 组件)

<x-layouts.auth>
    @livewire('auth.login')
</x-layouts.auth>

livewire 组件livewire/auth/login.blade.php

<form wire:submit.prevent="login" action="#" method="POST">
    <div>
        <label for="email">Email address</label>
        <input wire:model="email" id="email" type="email" required autofocus>
        @error('email'){{ $message }}@enderror
    </div>

    <div>
        <label for="password">Password</label>
        <input wire:model.lazy="password" id="password" type="password" required>
        @error('password'){{ $message }}@enderror
    </div>

    <div>
        <input wire:model.lazy="remember" id="remember_me" type="checkbox">
        <label for="remember_me">Remember me</label>

        <a href="#">Forgot your password?</a>
    </div>

    <div>
        <button type="submit">Sign in</button>
    </div>
</form>

和我Http/Livewire/Auth/Login.php的 livewire 组件文件:

class Login extends Component
{
    public $email = '';
    public $password = '';
    public $remember = false;

    protected $rules = [
        'email' => 'required|email|exists:users,email',
        'password' => 'required',
    ];

    /**
     * Shows Real time validation for email field
     */
    public function updatedEmail() {
        $this->validate(['email' => 'email|exists:users,email']);
    }

    /**
     * Logs user in when form is submitted
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Support\MessageBag
     */
    public function login()
    {
        // ******* Need to submit the form to Fortify here?? ******
    }

    /**
     * Renders the view
     * @return mixed
     */
    public function render()
    {
        return view('livewire.auth.login')
            ->layout('layouts.auth');
    }
}
4

3 回答 3

3
class Login extends Component
{
  public $email = '';
  public $password = '';
......

首先,根据Livewire 文档,敏感信息(例如密码)不应用作 livewire 组件中的公共属性。因此,在使用带有用户身份验证的 livewire 之前,您应该三思而后行。

protected $rules = [
  'email' => 'required|email|exists:users,email',
  'password' => 'required',
];

接下来,在您使用的验证规则中,存在:用户,电子邮件如果电子邮件在数据库中,它将实时验证。我建议不要在生产系统中将此验证与 livewire 实时验证规则一起使用,因为恶意行为者很容易使用它来提取系统用户的电子邮件列表。

话虽如此,您可以通过多种方式在登录功能中进行身份验证(但不使用 Fortify)。例如:

class LoginForm extends Component
{
public $email = '';
public $password = '';
public $remember = false;

protected $rules = [
    'email' => 'required|email|exists:users,email',
    'password' => 'required',
];

/*

Sometimes it's useful to validate a form field as a user types into it. 
Livewire makes "real-time" validation simple with the $this->validateOnly() method.

To validate an input field after every update, we can use Livewire's updated hook:

 */
public function updated($propertyName)
{
    $this->validateOnly($propertyName);
}

public function render()
{
    return view('livewire.loginForm');
}

public function login()
{
    $this->validate();

    // Execution doesn't reach here if validation fails.

    $email = $this->email;
    $password = $this->password;
    $credentials = ['email'=>$email, 'password'=>$password];

    if (Auth::attempt($credentials)) {
        // Auth success
    }

    else{
        // Auth failed
    }
}

}

再说一次,使用此方法时,您只是使用Fortify检索登录页面,这绝对不是Fortify的预期用途。因此,在考虑了所有问题之后,我认为最好避免使用 livewire 进行用户身份验证过程。

于 2021-01-23T01:32:36.013 回答
2

我尝试安装一个只有 Livewire 和 Fortify 的新项目来模拟您的场景。经过长时间的思考,这些是我的发现

  1. 当我看到 login() 方法并开始认为该方法将处理身份验证或转发它或其他什么时,这是最令人困惑的部分。
  2. Fortify 使用自己的路由,因此您无法在不将表单数据发送到“/login”端点的情况下进行身份验证。
  3. 您的 livewire 组件将帮助显示实时验证错误(也许您可以禁用表单提交按钮,直到验证通过)。
  4. 让 Fortify 为您处理身份验证并将您的表单设置为提交

<form method="POST" action="{{ route('login') }}">

  1. 如果您需要自定义身份验证过程,Fortify 很容易为您提供此功能,请参阅文档
  2. 如果您坚持使用 login() 方法,我认为您可以创建一个 PHP POST 请求来发送字段,但我看不出这样做的意义。

我希望这会给你这个想法。

于 2021-01-19T12:21:49.470 回答
0

我在 web.php 中添加路由如下:

Route::get('/login',Login::class)->middleware('guest')->name('login');

Login::class 是一个 livewire 组件,其中路径是 App\Http\Livewire\Auth\Login 。在 livewire/auth/login.blade.php 中存在一个按操作的表单:

<form method="POST" action="{{ route('login') }}"> .... </form>

通过 post 方法的 route('login') 与 Fortify 有关。

于 2021-09-24T09:26:04.757 回答