如何使用 Laravel 表单请求实现密码验证

介绍

Laravel 表单请求是扩展常规请求类功能的特殊类,允许 高级验证功能. 表单请求还有助于保持控制器操作更清洁,因为您可以将所有验证逻辑移动到表单请求类别。

在本指南中,我们将实施密码验证步骤,要求用户在访问管理员区域之前确认其密码。

前提条件

要遵循本指南,您需要一个运行Laravel 5.6+应用程序,其中包含内置的Laravel身份验证设置,请查看官方文档(https://laravel.com/docs/5.6/authentication)以了解如何设置此功能的详细信息。

步骤1 - 创建观点

我们将通过设置用户编辑个人资料页面开始。

在撰写本教程时,手工命令实用程序不会生成视图,因此我们需要手动创建视图。

创建文件 resources/views/profile/edit.blade.php 并添加以下代码。

 1@extends('layouts.app')
 2
 3@section('content')
 4<div class="container">
 5    @if (session('info'))
 6        <div class="row">
 7            <div class="col-md-12">
 8                <div class="alert alert-success alert-dismissible">
 9                    <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
10                    {{ session('info') }}
11                </div>
12            </div>
13        </div>        
14    @elseif (session('error'))
15        <div class="row">
16            <div class="col-md-12">
17                <div class="alert alert-danger alert-dismissible">
18                    <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
19                    {{ session('error') }}
20                </div>
21            </div>
22        </div>
23    @endif
24    <div class="row">
25        <div class="col-md-8 col-md-offset-2">
26            <div class="panel panel-default">
27                <div class="panel-heading">Update Profile</div>
28
29                <div class="panel-body">
30                    <form class="form-horizontal" method="POST" action="{{ route('profile.update', ['user' => $user]) }}">
31                        {{ csrf_field() }}
32                        {{ method_field('PUT') }}
33                        <div class="form-group{{ $errors->has('name') ? ' has-error' : '' }}">
34                            <label for="name" class="col-md-4 control-label">Name</label>
35                            <div class="col-md-6">
36                                <input id="name" type="text" class="form-control" name="name" value="{{ $user->name }}">
37
38                                @if ($errors->has('name'))
39                                    <span class="help-block">
40                                        <strong>{{ $errors->first('name') }}</strong>
41                                    </span>
42                                @endif
43                            </div>
44                        </div>
45
46                        <div class="form-group{{ $errors->has('password') ? ' has-error' : '' }}">
47                            <label for="password" class="col-md-4 control-label">Password</label>
48
49                            <div class="col-md-6">
50                                <input id="password" type="password" class="form-control" name="password">
51
52                                @if ($errors->has('password'))
53                                    <span class="help-block">
54                                        <strong>{{ $errors->first('password') }}</strong>
55                                    </span>
56                                @endif
57                            </div>
58                        </div>
59
60                        <div class="form-group">
61                            <label for="password-confirm" class="col-md-4 control-label">Confirm Password</label>
62
63                            <div class="col-md-6">
64                                <input id="password-confirm" type="password" class="form-control" name="password_confirmation">
65                            </div>
66                        </div>
67
68                        <div class="form-group{{ $errors->has('current_password') ? ' has-error' : '' }}">
69                            <label for="current-password" class="col-md-4 control-label">Current Password</label>
70
71                            <div class="col-md-6">
72                                <input id="current-password" type="password" class="form-control" name="current_password">
73
74                                @if ($errors->has('current_password'))
75                                    <span class="help-block">
76                                        <strong>{{ $errors->first('current_password') }}</strong>
77                                    </span>
78                                @endif
79                            </div>
80                        </div>
81
82                        <div class="form-group">
83                            <div class="col-md-6 col-md-offset-4">
84                                <button type="submit" class="btn btn-primary">
85                                    Update
86                                </button>
87                            </div>
88                        </div>
89                    </form>
90                </div>
91            </div>
92        </div>
93    </div>
94</div>
95@endsection

在我们的编辑个人资料页面上,我们检查一个信息错误闪存消息,并向用户显示它。

它有名称,密码,password_confirmationcurrent_password字段。

我们希望它工作的方式是,每当用户做出更改时,他们必须提供正确的current_password字段,以便将更新交付到数据库中。

密码密码_确认字段将允许用户更改他们的密码.如果它们都空,用户的当前密码将被保留,不会对其存储的密码进行更改。

在我们看来,主要参与者是密码,password_confirmationcurrent_password字段。

至于名称字段,它作为一个例子来扩展并为您的案例添加更多字段。

步骤 2 – 创建表格请求

现在,我们来谈谈本教程中最重要的部分。

执行以下命令创建表单请求。

1php artisan make:request UpdateProfile

上面的命令将创建一个名为app/Http/Requests/UpdateProfile.php的文件。

本节中的所有代码更改都将对此文件进行。

我们需要做的第一件事是名称(Laravel的哈希面孔)(LINK0)类声明之前。

1use Illuminate\Support\Facades\Hash;

接下来,我们需要从我们的授权方法返回真实,因为我们在表单请求中没有执行授权。

1/**
2 * Determine if the user is authorized to make this request.
3 *
4 * @return bool
5 */
6public function authorize()
7{
8    return true;
9}

我们的规则方法将返回描述此请求的验证规则的数组。

 1/**
 2 * Get the validation rules that apply to the request.
 3 *
 4 * @return array
 5 */
 6public function rules()
 7{
 8    return [
 9        'name' => 'required|string|max:255',
10        'password' => 'nullable|required_with:password_confirmation|string|confirmed',
11        'current_password' => 'required',
12    ];
13}

名称当前密码的规则是自我解释的。

密码规则规定,使用确认声明来确认密码。

它还声明‘required_with:password_confirmation’,这意味着如果用户提供密码确认,他们也应该提供密码。

这些验证规则将在我们在控制器操作中输入提示后自动检查每个请求(我们将在稍后进行)。

我们需要做的最后一件事是根据我们的要求声明一个与验证器的方法,在任何验证规则之前通过完全构建的验证器实例。

 1/**
 2 * Configure the validator instance.
 3 *
 4 * @param  \Illuminate\Validation\Validator  $validator
 5 * @return void
 6 */
 7public function withValidator($validator)
 8{
 9    // checks user current password
10    // before making changes
11    $validator->after(function ($validator) {
12        if ( !Hash::check($this->current_password, $this->user()->password) ) {
13            $validator->errors()->add('current_password', 'Your current password is incorrect.');
14        }
15    });
16    return;
17 }

在我们的与Valdator方法中,我们添加了一个之后链接,该函数将在所有验证检查完成后执行。

在我们的链接中,我们将用户提供的密码与其数据库中的密码进行比较。

$this->current_password给了我们current_password表单字段值,而Laravel允许我们使用$this->user()访问当前身份验证的用户,因此$this->user()->password给了我们用户存储在数据库中的哈希密码。

两种密码使用Hash面板的检查方法进行比较。

如果哈希检查失败,则将添加错误到验证器中,键为current_password,使用$validator->errors()->add('current_password',您的当前密码不正确。

这里是我们完整的UpdateProfile表格请求。

 1<?php
 2
 3namespace App\Http\Requests;
 4
 5use Illuminate\Foundation\Http\FormRequest;
 6
 7use Illuminate\Support\Facades\Hash;
 8
 9class UpdateProfile extends FormRequest
10{
11    /**
12     * Determine if the user is authorized to make this request.
13     *
14     * @return bool
15     */
16    public function authorize()
17    {
18        return true;
19    }
20
21    /**
22     * Get the validation rules that apply to the request.
23     *
24     * @return array
25     */
26    public function rules()
27    {
28        return [
29            'name' => 'required|string|max:255',
30            'password' => 'nullable|required_with:password_confirmation|string|confirmed',
31            'current_password' => 'required',
32        ];
33    }
34
35    /**
36     * Configure the validator instance.
37     *
38     * @param  \Illuminate\Validation\Validator  $validator
39     * @return void
40     */
41    public function withValidator($validator)
42    {
43        // checks user current password
44        // before making changes
45        $validator->after(function ($validator) {
46            if ( !Hash::check($this->current_password, $this->user()->password) ) {
47                $validator->errors()->add('current_password', 'Your current password is incorrect.');
48            }
49        });
50        return;
51    }
52}

步骤三:设置控制器

要使用我们的表单请求,我们需要在我们的控制器操作中键入提示。

执行以下命令来生成配置文件控制器。

1php artisan make:controller ProfileController

打开app/Http/Controllers/ProfileController.php文件并添加以下控制器操作。

 1public function __construct()
 2{
 3    $this->middleware('auth');
 4}
 5
 6/**
 7 * Show the form for editing the specified resource.
 8 *
 9 * @param  \App\User  $user
10 * @return \Illuminate\Http\Response
11 */
12public function edit(Request $request, User $user)
13{
14    // user
15    $viewData = [
16        'user' => $user,
17    ];
18    // render view with data
19    return view('profile.edit', $viewData);
20}
21
22/**
23 * Update the specified resource in storage.
24 *
25 * @param  \Illuminate\Http\Request  $request
26 * @param  \App\User  $user
27 * @return \Illuminate\Http\Response
28 */
29public function update(UpdateProfile $request, User $user)
30{
31    // form data
32    $data = $request->all();
33    $user->update($data);
34    return redirect(route('profile.edit', ['user' => $user]))
35                ->with('info', 'Your profile has been updated successfully.');
36}

配置文件控制器的构建器设置了Auth中间程序,以确保用户在编辑其个人资料之前已登录。

编辑操作为视图提供视图数据,而更新操作更新用户配置文件并重定向到编辑配置文件页面,并提供相应的闪存消息。

注意编辑操作的签名,我们已经键入了UpdateProfile请求,这就是我们需要做的,以启动我们UpdateProfile表单请求中的验证。

您还需要在控制器类声明之前代号表单请求和用户模型。

1use App\Http\Requests\UpdateProfile;
2use App\User;

步骤 4 – 设置受保护的路径和数据突变器

打开app/routes/web.php文件,并在控制器操作中添加以下代码。

1Route::get('/profile/{user}/edit', 'ProfileController@edit')->name('profile.edit');
2Route::put('/profile/{user}', 'ProfileController@update')->name('profile.update');

根据我们之前在我们的表单请求中添加的验证规则,可以通过一个无效密码。

在任何情况下,用户(或应用程序开发人员)都不会希望他们的密码设置为null或空串。

为了确保用户的密码只有在他们提供密码时才会设置,我们将使用 Eloquent ORM的突变器

打开app/User.php文件并添加以下代码。

1// Only accept a valid password and 
2// hash a password before saving
3public function setPasswordAttribute($password)
4{
5    if ( $password !== null & $password !== "" )
6    {
7        $this->attributes['password'] = bcrypt($password);
8    }
9}

语气变异器必须遵循命名方案设置<camel-cased-attribute-name>Attribute

由于我们声明了密码属性的一个突变体,因此我们命名了这种突变体为setPasswordAttribute

突变函数通过了被设置的值,在我们的突变器中是$password变量。

在我们的突变器中,我们检查$password变量是否为null或一个空串,并使用$this->attributes[password]在我们的模型中设置它。

此外,请注意,密码在保存之前被哈希,所以我们不必在我们的应用程序中其他地方进行。

默认的LaravelAuth/RegisterControllerAuth/ResetPasswordController在坚持到数据库之前也对密码进行哈希,所以我们需要在声明上述突变器后更新各个控制器中的创建重置Password方法。

打开app/Http/Controllers/Auth/RegisterController.php文件并添加以下代码。

 1/**
 2 * Create a new user instance after a valid registration.
 3 *
 4 * @param array  $data
 5 * @return \App\User
 6 */
 7protected function create(array $data)
 8{
 9    return User::create([
10        'name' => $data['name'],
11        'email' => $data['email'],
12        'password' => $data['password'],
13    ]);
14}

打开app/Http/Controllers/Auth/ResetPasswordController.php文件并添加以下代码。

 1/**
 2 * Reset the given user's password.
 3 *
 4 * @param  \Illuminate\Contracts\Auth\CanResetPassword  $user
 5 * @param string  $password
 6 * @return void
 7 */
 8protected function resetPassword($user, $password)
 9{
10    $user->password = $password;
11
12    $user->setRememberToken(Str::random(60));
13
14    $user->save();
15
16    event(new PasswordReset($user));
17
18    $this->guard()->login($user);
19}

对于ResetPasswordController,您还需要在类声明之前使用的相应类别。

1use Illuminate\Support\Str;
2use Illuminate\Auth\Events\PasswordReset;

我们已经完成了,我们的密码验证按预期工作。

结论

在本指南中,我们看到如何实施额外的密码验证步骤,以确认用户有权访问管理区域,我们已经看到如何创建和设置表单请求以在Laravel应用程序中实施表单验证。

有关验证和表单请求的更多信息,您可以查看 官方Laravel文档

Published At
Categories with 技术
comments powered by Disqus