使用 Laravel Livewire 和 Laravel Fortify 进行登录
Posted
技术标签:
【中文标题】使用 Laravel Livewire 和 Laravel Fortify 进行登录【英文标题】:Use Laravel Livewire with Laravel Fortify for Login 【发布时间】:2021-02-19 13:10:48 【问题描述】:我想使用 Laravel Fortify 和 Livewire 创建一个非常简单的登录表单。我不想使用 Jetstream,因为它有更多我不需要的功能和我需要的功能。
我在整个应用程序中都使用 livewire,并希望将它用于我的登录页面以提供实时即时验证。
我遇到的问题是,如果我在输入上使用wire:model
,我将无法提交带有值的表单。
我也不能使用auth()->attempt()
,因为它被Fortify劫持了。(至少,我认为是。众所周知,当我使用它时,它会返回false
)
如何在 fortify 中使用 livewire?我需要将 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');
【问题讨论】:
【参考方案1】:class Login extends Component public $email = ''; public $password = ''; ......
首先,根据Livewire documentation,敏感信息(如密码)不应该用作livewire组件中的公共属性。因此,在使用带有用户身份验证的 livewire 之前,您应该三思。
protected $rules = [ 'email' => 'required|email|exists:users,email', 'password' => 'required', ];
接下来,在验证规则中,您将使用 exists:user,email,如果电子邮件在数据库中,它将实时验证。我建议不要在生产系统中将此验证与 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 进行用户身份验证过程。
【讨论】:
感谢您指出安全隐患以及在 Fortify 中使用传统 POST 表单完成身份验证的原因。我在 Fortify 的文档中对此进行了解释。 @codingFriend1 您是否在此评论中针对我? @AliAli 完全没有,除非是您编写了 Jetstream 文档(但在这种情况下,这并不是一种冒犯,而是一种善意的建议)我真的很感谢您对这个问题的回答很多,也赞成。我只是认为安全考虑比实际解决方案更重要。此外,在我上面的评论中,我实际上是指 LiveWire 文档的 Jetstream,而不是 Fortify 文档。【参考方案2】:我尝试安装一个只有 Livewire 和 Fortify 的新项目来模拟您的场景。 经过长时间的思考,这是我的发现
-
当我看到 login() 方法和
开始认为此方法将处理身份验证或
转发它什么的。
Fortify 使用自己的路由,因此您无法在没有的情况下进行身份验证
将表单数据发送到“/login”端点。
您的 livewire 组件将帮助显示实时
验证错误,(也许您可以禁用表单提交按钮
直到验证通过)。
让 Fortify 为您处理身份验证并将您的表单设置为
提交
<form method="POST" action=" route('login') ">
-
如果您需要自定义身份验证过程,Fortify 提供
你这个功能很容易,看documentation
如果你坚持使用 login() 方法我认为你可以创建一个 PHP POST
请求发送字段,但我看不出这样做的意义。
我希望这会给你这个想法。
【讨论】:
所以最后,您不能在登录页面中使用完整页面的 LiveWire 组件,而只能将单个 LiveWire 组件(如带有动态错误输出的表单本身)包含到常规登录刀片视图中,并且仍然将表单作为常规 POST 提交。我想整个事情只是令人困惑,因为 Jetstream 有一个使用 Fortify 的 LiveWire 版本,但实际上 Fortify 显然不是在考虑 LiveWire 的情况下构建的。因此,Jetstream 也使用常规的完整页面视图进行登录。 是的,确实,很混乱,但事实就是这样。【参考方案3】:我在 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>
那个 route('login') by post 方法与 Fortify 相关。
【讨论】:
以上是关于使用 Laravel Livewire 和 Laravel Fortify 进行登录的主要内容,如果未能解决你的问题,请参考以下文章
Laravel 与 JetStream 和 LiveWire 不渲染(尾风)
Laravel 和 Livewire:组件更改时如何执行 javascript 函数?
dompdf 没有从 Laravel 8 和 Livewire 视图下载 PDF