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 info
và info
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 password
và password_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
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 name
và current_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
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/RegisterController
và Auth/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 create
và resetPassword
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.
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 .
Các tin liên quan