Thứ năm, 12/12/2019 | 00:00 GMT+7

Cách thực hiện xác minh mật khẩu bằng yêu cầu biểu mẫu Laravel

Yêu cầu biểu mẫu Laravel là các lớp đặc biệt mở rộng chức năng của các lớp yêu cầu thông thường, cho phép các tính năng xác thực nâng cao . Yêu cầu biểu mẫu cũng giúp giữ cho các hành động của bộ điều khiển của bạn gọn gàng hơn rất nhiều, vì bạn có thể di chuyển tất cả logic xác thực của bạn sang lớp yêu cầu biểu mẫu. Một lợi ích khác là nó cho phép bạn lọc các yêu cầu trước khi chúng tiếp cận các hành động của bộ điều khiển của bạn.

Trong hướng dẫn này, ta sẽ triển khai bước xác minh password để yêu cầu user xác nhận password của họ trước khi truy cập khu vực quản trị. Phương pháp này hoạt động như một kiểm tra kỹ và cung cấp cho ứng dụng của bạn một lớp bảo mật bổ sung.

Yêu cầu

Để làm theo hướng dẫn này, bạn cần một ứng dụng Laravel 5.6+ hoạt động với xác thực Laravel tích hợp được cài đặt . Vui lòng kiểm tra tài liệu chính thức để biết chi tiết về cách cài đặt điều này.

Bước 1 - Tạo Chế độ xem

Ta sẽ bắt đầu bằng cách cài đặt trang tiểu sử chỉnh sửa của user .

Tại thời điểm viết hướng dẫn này, tiện ích lệnh artisan không tạo chế độ xem nên ta cần tạo chế độ xem theo cách thủ công.

Tạo resources/views/profile/edit.blade.php file resources/views/profile/edit.blade.php và thêm mã sau.

@extends('layouts.app')  @section('content') <div class="container">     @if (session('info'))         <div class="row">             <div class="col-md-12">                 <div class="alert alert-success alert-dismissible">                     <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>                     {{ session('info') }}                 </div>             </div>         </div>             @elseif (session('error'))         <div class="row">             <div class="col-md-12">                 <div class="alert alert-danger alert-dismissible">                     <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>                     {{ session('error') }}                 </div>             </div>         </div>     @endif     <div class="row">         <div class="col-md-8 col-md-offset-2">             <div class="panel panel-default">                 <div class="panel-heading">Update Profile</div>                  <div class="panel-body">                     <form class="form-horizontal" method="POST" action="{{ route('profile.update', ['user' => $user]) }}">                         {{ csrf_field() }}                         {{ method_field('PUT') }}                         <div class="form-group{{ $errors->has('name') ? ' has-error' : '' }}">                             <label for="name" class="col-md-4 control-label">Name</label>                             <div class="col-md-6">                                 <input id="name" type="text" class="form-control" name="name" value="{{ $user->name }}">                                  @if ($errors->has('name'))                                     <span class="help-block">                                         <strong>{{ $errors->first('name') }}</strong>                                     </span>                                 @endif                             </div>                         </div>                          <div class="form-group{{ $errors->has('password') ? ' has-error' : '' }}">                             <label for="password" class="col-md-4 control-label">Password</label>                              <div class="col-md-6">                                 <input id="password" type="password" class="form-control" name="password">                                  @if ($errors->has('password'))                                     <span class="help-block">                                         <strong>{{ $errors->first('password') }}</strong>                                     </span>                                 @endif                             </div>                         </div>                          <div class="form-group">                             <label for="password-confirm" class="col-md-4 control-label">Confirm Password</label>                              <div class="col-md-6">                                 <input id="password-confirm" type="password" class="form-control" name="password_confirmation">                             </div>                         </div>                          <div class="form-group{{ $errors->has('current_password') ? ' has-error' : '' }}">                             <label for="current-password" class="col-md-4 control-label">Current Password</label>                              <div class="col-md-6">                                 <input id="current-password" type="password" class="form-control" name="current_password">                                  @if ($errors->has('current_password'))                                     <span class="help-block">                                         <strong>{{ $errors->first('current_password') }}</strong>                                     </span>                                 @endif                             </div>                         </div>                          <div class="form-group">                             <div class="col-md-6 col-md-offset-4">                                 <button type="submit" class="btn btn-primary">                                     Update                                 </button>                             </div>                         </div>                     </form>                 </div>             </div>         </div>     </div> </div> @endsection 

Trong trang “chỉnh sửa profile ” của ta , ta kiểm tra infoinfo error flash và hiển thị nó cho user .

Nó có name , password , password_confirmation và trường current_password .

Cách ta muốn nó hoạt động là khi nào user thực hiện thay đổi, họ phải cung cấp trường current_password chính xác để commit cập nhật vào database .

Trường passwordpassword_confirmation sẽ cho phép user thay đổi password của họ. Nếu cả hai đều để trống, password hiện tại của user sẽ được giữ lại và không có thay đổi nào đối với password đã lưu của họ.

Các yếu tố chính trong quan điểm của ta là password , password_confirmation , và current_password .

Đối với trường name , nó phục vụ như một ví dụ để mở rộng và thêm nhiều trường hơn cho trường hợp của bạn.

Bước 2 - Tạo yêu cầu biểu mẫu

Bây giờ đến phần quan trọng nhất của hướng dẫn này.

Thực hiện lệnh sau để tạo một yêu cầu biểu mẫu.

  • php artisan make:request UpdateProfile

Nghệ nhân Yêu cầu

Lệnh trên sẽ tạo một file có tên app/Http/Requests/UpdateProfile.php .

Tất cả các thay đổi mã trong phần này sẽ được thực hiện cho file này.

Điều đầu tiên ta cần làm là đặt alias Laravel's Hash trước khi khai báo lớp.

use Illuminate\Support\Facades\Hash; 

Tiếp theo, ta cần trả về true từ phương thức authorize vì ta không thực hiện ủy quyền trong yêu cầu biểu mẫu của bạn .

/**  * Determine if the user is authorized to make this request.  *  * @return bool  */ public function authorize() {     return true; } 

Phương thức luật của ta sẽ trả về mảng phác thảo các luật xác thực cho yêu cầu này.

/**  * Get the validation rules that apply to the request.  *  * @return array  */ public function rules() {     return [         'name' => 'required|string|max:255',         'password' => 'nullable|required_with:password_confirmation|string|confirmed',         'current_password' => 'required',     ]; } 

Các luật namecurrent_password là tự giải thích.

Các luật password nói rằng password sẽ được xác nhận bằng cách sử dụng khai báo confirmed .

Nó cũng khai báo Requi_with required_with:password_confirmation nghĩa là nếu user cung cấp xác nhận password , họ cũng phải cung cấp password .

Các luật xác thực này sẽ được kiểm tra tự động theo mọi yêu cầu sau khi ta nhập gợi ý nó trong hành động trình điều khiển của ta (mà ta sẽ thực hiện sau).

Điều cuối cùng ta cần làm là khai báo một phương thức withValidator theo yêu cầu của ta . Phương thức này được thông qua version trình xác thực được xây dựng đầy đủ trước khi bất kỳ luật xác thực nào kích hoạt.

/**  * Configure the validator instance.  *  * @param  \Illuminate\Validation\Validator  $validator  * @return void  */ public function withValidator($validator) {     // checks user current password     // before making changes     $validator->after(function ($validator) {         if ( !Hash::check($this->current_password, $this->user()->password) ) {             $validator->errors()->add('current_password', 'Your current password is incorrect.');         }     });     return;  } 

Bên trong phương thức withValdator của ta , ta đã thêm một dấu móc after , một hàm sẽ được thực thi sau khi tất cả các kiểm tra xác thực đã được thực hiện.

Trong phần after của ta , ta đã so sánh password được cung cấp của user với password của họ được đặt trong database .

$this->current_password cung cấp cho ta giá trị trường biểu mẫu current_password trong khi Laravel cho phép ta truy cập vào user hiện được xác thực bằng cách sử dụng $this->user() vì vậy $this->user()->password cung cấp cho ta password đã băm của user được lưu trong repository dữ liệu.

Hai password được so sánh bằng cách sử dụng phương pháp check của mặt tiền Hash .

Nếu kiểm tra băm không thành công, một lỗi sẽ được thêm vào trình xác thực với khóa current_password bằng cách sử dụng $validator->errors()->add('current_password', 'Your current password is incorrect.') .

Đây là yêu cầu biểu mẫu UpdateProfile hoàn chỉnh của ta .

<?php  namespace App\Http\Requests;  use Illuminate\Foundation\Http\FormRequest;  use Illuminate\Support\Facades\Hash;  class UpdateProfile extends FormRequest {     /**      * Determine if the user is authorized to make this request.      *      * @return bool      */     public function authorize()     {         return true;     }      /**      * Get the validation rules that apply to the request.      *      * @return array      */     public function rules()     {         return [             'name' => 'required|string|max:255',             'password' => 'nullable|required_with:password_confirmation|string|confirmed',             'current_password' => 'required',         ];     }      /**      * Configure the validator instance.      *      * @param  \Illuminate\Validation\Validator  $validator      * @return void      */     public function withValidator($validator)     {         // checks user current password         // before making changes         $validator->after(function ($validator) {             if ( !Hash::check($this->current_password, $this->user()->password) ) {                 $validator->errors()->add('current_password', 'Your current password is incorrect.');             }         });         return;     } } 

Bước 3 - Cài đặt bộ điều khiển

Để sử dụng yêu cầu biểu mẫu của ta , ta cần nhập gợi ý nó trong hành động trình điều khiển của ta .

Thực hiện lệnh sau để tạo bộ điều khiển profile .

  • php artisan make:controller ProfileController

Artisan Make Controller

Mở app/Http/Controllers/ProfileController.php file app/Http/Controllers/ProfileController.php và thêm các hành động điều khiển sau.

public function __construct() {     $this->middleware('auth'); }  /**  * Show the form for editing the specified resource.  *  * @param  \App\User  $user  * @return \Illuminate\Http\Response  */ public function edit(Request $request, User $user) {     // user     $viewData = [         'user' => $user,     ];     // render view with data     return view('profile.edit', $viewData); }  /**  * Update the specified resource in storage.  *  * @param  \Illuminate\Http\Request  $request  * @param  \App\User  $user  * @return \Illuminate\Http\Response  */ public function update(UpdateProfile $request, User $user) {     // form data     $data = $request->all();     $user->update($data);     return redirect(route('profile.edit', ['user' => $user]))                 ->with('info', 'Your profile has been updated successfully.'); } 

Phương thức khởi tạo của trình điều khiển profile đặt phần mềm trung gian auth đảm bảo user đã đăng nhập trước khi chỉnh sửa profile của họ.

Các edit hành động phục vụ vùng đang xem với các dữ liệu quan điểm trong khi update hành động cập nhật profile user và chuyển hướng quay về trang chỉnh sửa profile cá nhân với thông điệp đèn flash tương ứng.

Lưu ý chữ ký của hành động edit nơi ta đã nhập gợi ý yêu cầu UpdateProfile , đây là tất cả những gì ta cần làm để kích hoạt các xác thực bên trong yêu cầu biểu mẫu UpdateProfile của ta .

Bạn cũng cần đặt alias cho yêu cầu biểu mẫu và mô hình user trước khi khai báo lớp bộ điều khiển.

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

Bước 4 - Cài đặt các tuyến được bảo vệ và bộ đột biến dữ liệu

Mở app/routes/web.php file app/routes/web.php và thêm mã sau để liên kết các hành động của bộ điều khiển.

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

Dựa trên luật xác thực mà ta đã thêm trước đó vào yêu cầu biểu mẫu của bạn , password null thể được chuyển qua.

Trong mọi trường hợp, user (hoặc nhà phát triển ứng dụng) muốn password của họ được đặt thành null hoặc một chuỗi trống.

Để đảm bảo password user chỉ được đặt khi họ cung cấp password , ta sẽ sử dụng các trình đột biến của Eloquent ORM .

Mở app/User.php file app/User.php và thêm mã sau.

// Only accept a valid password and  // hash a password before saving public function setPasswordAttribute($password) {     if ( $password !== null & $password !== "" )     {         $this->attributes['password'] = bcrypt($password);     } } 

Những kẻ đột biến hùng hồn phải tuân theo sơ đồ đặt tên set<camel-cased-attribute-name>Attribute .

Vì ta đang khai báo một trình đột biến cho thuộc tính password ta đã đặt tên cho trình đột biến là setPasswordAttribute .

Hàm mutator được chuyển giá trị đang được đặt trong hàm mutator của ta là biến $password .

Trong trình biến đổi của ta , ta kiểm tra xem biến $password không phải là null hay là một chuỗi rỗng và đặt nó trong mô hình của ta bằng cách sử dụng $this->attributes['password'] .

Cũng lưu ý password được băm trước khi lưu để ta không phải thực hiện ở nơi khác trong ứng dụng của bạn .

Mặc định Laravel Auth/RegisterControllerAuth/ResetPasswordController cũng băm password trước khi lưu nó vào database , vì vậy ta cần cập nhật phương thức createresetPassword trong các bộ điều khiển tương ứng sau khi khai báo trình đột biến ở trên.

Mở app/Http/Controllers/Auth/RegisterController.php file app/Http/Controllers/Auth/RegisterController.php và thêm mã sau.

/**  * Create a new user instance after a valid registration.  *  * @param  array  $data  * @return \App\User  */ protected function create(array $data) {     return User::create([         'name' => $data['name'],         'email' => $data['email'],         'password' => $data['password'],     ]); } 

Mở app/Http/Controllers/Auth/ResetPasswordController.php file app/Http/Controllers/Auth/ResetPasswordController.php và thêm mã sau.

/**  * Reset the given user's password.  *  * @param  \Illuminate\Contracts\Auth\CanResetPassword  $user  * @param  string  $password  * @return void  */ protected function resetPassword($user, $password) {     $user->password = $password;      $user->setRememberToken(Str::random(60));      $user->save();      event(new PasswordReset($user));      $this->guard()->login($user); } 

Đối với ResetPasswordController , bạn cũng cần đặt alias cho các lớp tương ứng được sử dụng trước khi khai báo lớp.

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

Tất cả ta đã hoàn thành và xác minh password của ta hoạt động như mong đợi.

Quá trình chạy thử ứng dụng khi cung cấp password không chính xác hoặc không có password nào dẫn đến hành vi sau được minh họa bằng ảnh chụp màn hình.

Mật khẩu không đúng

Mật khẩu được yêu câu

Kết luận

Trong hướng dẫn này, ta đã biết cách triển khai bước xác minh password bổ sung để khẳng định rằng user được phép truy cập vào khu vực quản trị. Ta đã biết cách tạo và cài đặt yêu cầu biểu mẫu để triển khai xác thực biểu mẫu trong ứng dụng Laravel.

Để biết thêm thông tin về xác thực và yêu cầu biểu mẫu, bạn có thể kiểm tra tài liệu chính thức của Laravel .


Tags:

Các tin liên quan