Xin chào anh em, như anh em cũng biết là một hệ thống nào cũng cần có xác thực khi thực hiện một hoặc nhiều hành vi mà hệ thống cho phép. Để tiếp tục series Laravel và những điều thú vị thì hôm nay mình sẽ giới thiệu với các bạn Authentication
trong Laravel - nó xây dựng giúp cho việc thực hiện xác thực vô cùng đơn giản. Bạn sẽ không ngờ được là Laravel nó xây dựng sẵn, chúng ta chỉ việc dùng và tùy ý theo chúng ta muốn mà thôi. Nào chúng ta hãy bắt tay đi tìm hiểu nó thôi.
1. Giới thiệu
Lướt qua phần config tí nhé, chúng ta sẽ thấy có một file config/auth.php
<?php return [ /* |-------------------------------------------------------------------------- | Authentication Defaults |-------------------------------------------------------------------------- | | This option controls the default authentication "guard" and password | reset options for your application. You may change these defaults | as required, but they're a perfect start for most applications. | */ 'defaults' => [ 'guard' => 'web', 'passwords' => 'users', ], /* |-------------------------------------------------------------------------- | Authentication Guards |-------------------------------------------------------------------------- | | Next, you may define every authentication guard for your application. | Of course, a great default configuration has been defined for you | here which uses session storage and the Eloquent user provider. | | All authentication drivers have a user provider. This defines how the | users are actually retrieved out of your database or other storage | mechanisms used by this application to persist your user's data. | | Supported: "session", "token" | */ 'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'token', 'provider' => 'users', ], ], /* |-------------------------------------------------------------------------- | User Providers |-------------------------------------------------------------------------- | | All authentication drivers have a user provider. This defines how the | users are actually retrieved out of your database or other storage | mechanisms used by this application to persist your user's data. | | If you have multiple user tables or models you may configure multiple | sources which represent each model / table. These sources may then | be assigned to any extra authentication guards you have defined. | | Supported: "database", "eloquent" | */ 'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App\User::class, ], // 'users' => [ // 'driver' => 'database', // 'table' => 'users', // ], ], /* |-------------------------------------------------------------------------- | Resetting Passwords |-------------------------------------------------------------------------- | | You may specify multiple password reset configurations if you have more | than one user table or model in the application and you want to have | separate password reset settings based on the specific user types. | | The expire time is the number of minutes that the reset token should be | considered valid. This security feature keeps tokens short-lived so | they have less time to be guessed. You may change this as needed. | */ 'passwords' => [ 'users' => [ 'provider' => 'users', 'table' => 'password_resets', 'expire' => 60, ], ],
];
Hệ thống xác thực Authentication của Laravel được xây dựng dựa trên 2 thành phần cốt lõi - guard và provider.
Guards
Guard
các bạn cứ hiểu như là một cách cung cấp logic được dùng để xác thực người dùng. Trong Laravel, thường hay dùng session guard
hoặc token guard
. Session
guard duy trì trạng thái người dùng trong mỗi lần request bằng cookie. Còn Token
guard xác thực người dùng bằng cách kiểm tra token hợp lệ trong mỗi lần request.
Vì vậy, như bạn thấy, guard xác định logic của việc xác thực, và không cần thiết để luôn xác thực bằng cách lấy các thông tin hợp lệ từ phía back-end. Bạn có thể triển khai một guard mà chỉ cần kiểm tra sự có mặt của một thông tin cụ thể trong headers của request và xác thực người dùng dựa trên điều đó.
Providers
Nếu Guards
hỗ trợ việc định nghĩa logic để xác thực thì Providers
lấy ra dữ liệu người dùng từ phía back-end. Nếu guard yêu cầu người dùng phải hợp lệ với bộ lưu trữ ở back-end thì việc triển khai truy suất người dùng sẽ được providers thực hiện.Laravel hỗ trợ cho việc người dùng truy suất sử dụng Eloquent và Query Buider vào database. Tuy nhiên, chúng ta có thể thêm bất kì thay đổi vào . Ví dụ nhé, các bạn đặt model User trong namespace App nữa mà các bạn muốn đặt trong namespace App\Model thì chúng ta sẽ thay đỏi providers
tronbg file app/auth.php
như sau :
'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App\Model\User::class, ], // 'users' => [ // 'driver' => 'database', // 'table' => 'users', // ], ],
Chúng ta đăng ký tài khoản với hệ thống thì trường password thì phải tối thiểu 60 ký tự và tối đa 255 ký tự nhé. Chúng ta cũng có thể đổi thay đổi cho trường remember_token
là nullable()
khi migrate bảng users
.Ak mình nới thêm chút về cái trường remember_token
- đây là trường sẽ lưu token để giành cho chức năng Remember me
mình sẽ giới thiệu ở phần sau nhé.
Đừng lo lắng nhé nếu mà chúng ta cứ sử dụng như default thì chúng ta chẳng cần động vào file config/auth.php
này làm gì !!!!
2.Làm quen với Authentication trong Laravel
Controller
Laravel sẽ có một vài các controller của Authentication có sẵn trong prject Laravel của chúng ta. Nó nằm ở App\Http\Controller\Auth namespace và chúng nằm trong folder app/Http/Controllers/Auth
Chúng ta cùng điểm qua một chút xem các controller này làm gì nhé
ForgotPasswordController
dùng để cho điều khiển cho chức năng khi người dùng quên mật khẩu, thì hệ thống sẽ bắt người dùng nhập mail đăng ký với hệ thống để gửi mật khẩu mới.
LoginController
làm nhiệm vụ điều khiển khi người dùng đăng nhập vào hệ thống. Người dùng sẽ đăng nhập bằng mail với mật khẩu khi đăng kí với hệ thông.
RegisterController
làm nhiệm vụ đăng ký một thành viên mới trong hệ thống
với các
ResetPasswordController
làm nhiệm vụ điều khiển khi một user muốn thay đổi mật khẩu tài khoản đăng nhập hệ thống.
Thành phần được sinh ra
Để bắt đầu thực hiện công việc xác thực cho hệ thống chúng ta hãy thực hiền 2 câu lệnh sau:
php artisan make:auth php artisan migrate // Dùng để migrate 2 bảng users và password_resets có sẵn trong project khi mới init
Khi thực hiện xong thì hệ thống sẽ sinh ra cho chúng ta những thứ sau. Thứ nhất các bạn vào routes/web.php
sẽ thấy những dòng code này sinh ra
Auth::routes(); Route::get('/home', '_@.com')->name('home');
Vậy chúng ta cũng có thể hiểu, hệ thống sẽ tự sinh ra cho chúng ta những route để phục vụ cho việc login, logout, register, forgot password. Các bạn cũng có thể sử dụng câu lệnh php artisan route:list
để xem được các thông tin như sau :
+--------+---------------+------------------------+------------------+------------------------------------------------------------------------+--------------+
| Domain | Method | URI | Name | Action | Middleware |
+--------+---------------+------------------------+------------------+------------------------------------------------------------------------+--------------+
| | GET|HEAD | / | | Closure | web |
| | GET|HEAD | api/user | | Closure | api,auth:api |
| | GET|POST|HEAD | broadcasting/auth | | Illuminate\Broadcasting\BroadcastController@authenticate | web |
| | GET|HEAD | home | home | App\Http\Controllers\HomeController@index | web,auth |
| | GET|HEAD | home/loginUser | | App\Http\Controllers\HomeController@index | web,auth |
| | GET|HEAD | home/logoutUser | | App\Http\Controllers\HomeController@onLogout | web,auth |
| | GET|HEAD | login | login | App\Http\Controllers\Auth\LoginController@showLoginForm | web,guest |
| | POST | login | | App\Http\Controllers\Auth\LoginController@login | web,guest |
| | POST | logout | logout | App\Http\Controllers\Auth\LoginController@logout | web |
| | POST | password/email | password.email | App\Http\Controllers\Auth\ForgotPasswordController@sendResetLinkEmail | web,guest |
| | GET|HEAD | password/reset | password.request | App\Http\Controllers\Auth\ForgotPasswordController@showLinkRequestForm | web,guest |
| | POST | password/reset | | App\Http\Controllers\Auth\ResetPasswordController@reset | web,guest |
| | GET|HEAD | password/reset/{token} | password.reset | App\Http\Controllers\Auth\ResetPasswordController@showResetForm | web,guest |
| | GET|HEAD | register | register | App\Http\Controllers\Auth\RegisterController@showRegistrationForm | web,guest |
| | POST | register | | App\Http\Controllers\Auth\RegisterController@register | web,guest |
+--------+---------------+------------------------+------------------+------------------------------------------------------------------------+--------------+
Ngoài ra trong app/Http/Controllers sẽ sinh ra HomeController
, và các bạn lưu ý một điều là khi chúng ta enter câu lệnh php artisan make:auth
thì nếu chúng ta có file HomeController.php
trong folder app/Http/Controllers thì hệ thống sẽ báo là chúng ta có muốn xóa file HomeController.php cũ đó đi để sinh ra một file HomeController.php mới hay không. Nếu không thì vẫn giữ nguyên file HomeController.php cũ ban đầu.
Tiếp nữa các bạn vào folder resource/views
thì ở đây sé sinh ra một folder chứa các template của auth, và một template home.blade.php
.
Tùy biến Path trong controller
Ở trong LoginController, RegisterController, ResetPasswordController
các bạn có thấy biến $redirect
không, biến này giúp chúng ta điều chỉnh lại cái đường dẫn mà khi ta làm xong công việc login, register, reset password sẽ redirect tới đường dẫn mà ta tùy chỉnh.
protected $redirectTo = '/home';
Khi user không được xác nhận thành công, họ sẽ tự động chuyển hướng quay lại form đăng nhập.
Tiếp theo bạn cũng có thể điều chỉnh trong middeware RedirectIfAuthenticated
public function handle($request, Closure $next, $guard = null) { if (Auth::guard($guard)->check()) { return redirect('/home'); } return $next($request); }
Tùy biến Username, Guard
Theo mặc định của Laravel thì sẽ đăng nhập bằng email
. Nếu muốn tùy chỉnh thì chúng ta cũng có thể vào LoginController
để định nghĩa method username
public function username()
{ return 'username';
}
Chúng ta cũng có thể tùy biến guard
- sử dụng để xác thực user. Để bắt đầu, định nghĩa một phương thức guard
trong LoginController, RegisterController, ResetPasswordController
. Hàm này sẽ trả về một thể hiển guard.
use Illuminate\Support\Facades\Auth; protected function guard()
{ return Auth::guard('guard-name');
}
Tùy biến Validator, Storage khi register
Trong RegisterController
các bạn cũng có thể customize lại một thành viên mới đăng ký như nào. Các bạn có thể thêm trường cho bảng users
để lưu nhiều thông tin về user khi đang ký hơn.
Ví dụ theo bảng users
có sẵn trong Laravel thì chỉ có các trường như này
<?php use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration; class CreateUsersTable extends Migration
{ /** * Run the migrations. * * @return void */ public function up() { Schema::create('users', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->string('email')->unique(); $table->string('password'); $table->rememberToken(); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('users'); }
}
Các bạn có thể tạo 1 file mới migration mới và thêm các trường cho bảng users
public function up() { Schema::table('users', function (Blueprint $table) { $table->string('address'); $table->string('phone'); $table->integer('role'); }); }
Tiếp tục chúng ta sẽ cho hiển thị thêm 2 trường input để nhập address và phone của người dùng, nhớ thêm các trường vừa thêm trong biến $fillable
của model User nhé. Sau đó trong RegisterController chúng ta sẽ thêm như sau :
protected function validator(array $data) { return Validator::make($data, [ 'name' => 'required|string|max:255', 'email' => 'required|string|email|max:255|unique:users', 'password' => 'required|string|min:6|confirmed', // thêm validate cho các trường vừa thêm 'address' => 'required', 'phone' => 'required', ]); } /** * 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' => Hash::make($data['password']), 'address' => $data['address'], 'phone' => $data['phone'], 'role' => 2, // ý muốn là lưu user nếu hệ thông có role = 1 là admin, 2 là user :))) ]); }
Đây là ví dụ mình muốn customize lại phần register, nhưng trong thực tế thì người dùng ko mong muốn phải nhập nhiều dữ liệu như này, chúng ta có thể cho người dùng đăng ký các trường mặc định như trong Laravel, có điều vào phần chức năng chỉnh sửa Profile thì chúng ta mới cho update cập nhật thông tin người dùng !!!
Truy suất người dùng đã xác thực
Khi mà các bạn đăng nhập thành công hệ thống thì các bạn có thể truy cập thông tin người dùng đã xác thực ở mọi nơi. Các bạn cần use use Illuminate\Support\Facades\Auth
để sử dụng Auth
nhé.
$id = Auth::user()->id; hoặc Auth::id() //Lấy về ID người .
$user = Auth::user() // Lấy về tất cả các thông tin của người dùng.
$email = Auth::user()->email // Lây về email người dùng.
...
Để xem người dùng đã xác thực (đăng nhập được vào hệ thống) hay chưa thì dùng
if (Auth::check()) {
echo "Nguoi dung da dang nhap he thong";
}
Middleware
Trong Laravel , authentication có middleware auth
, hệ thống muốn chắc chắn rằng người dùng phải đăng nhập xác thực trước khi được làm một số các thao tác đối với hệ thống. Middleware nằm trong ở app/Http/Middleware/RedirectIfAuthenticated.php
. Các bạn có thể sử dụng ngay ở routes
hoặc trong hàm __contruct()
ở mỗi Controller.
Route::get('profile', function () { // Only authenticated users may enter...
})->middleware('auth');
public function __construct()
{ $this->middleware('auth');
}
Khi bạn gán dùng middleware auth trong route, bạn cũng có thể chỉ định guard nào sẽ được sử dụng để thực hiện công việc xác thực. Nhưng những guard mà bạn có thể lựa chọn chỉ được lựa auth.php
'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'token', 'provider' => 'users', ], ],
Ví dụ
public function __construct()
{ $this->middleware('auth:api');
}
3.Xác thực người dùng thủ công
Nhiều bạn không muốn dùng authentication controller có sẵn để xác thực người dùng. Đừng lo lắng về vấn đề đấy, chúng ta có thể tự xác thực theo ý muôn của chúng ta bằng cách sử dụng các class có sẵn ở Auth
. Hãy chú ý import Illuminate\Support\Facades\Auth
<?php namespace App\Http\Controllers; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth; class LoginController extends Controller
{ /** * Handle an authentication attempt. * * @param \Illuminate\Http\Request $request * * @return Response */ public function authenticate(Request $request) { $credentials = $request->only('email', 'password'); if (Auth::attempt($credentials)) { // Authentication passed... return redirect()->intended('dashboard'); } }
}
Giải thích một chút nhé: Khi ta sử dụng Auth::attempt()
nó sẽ nhận vào một mảng các key/value , như ví dụ ở trên thì hệ thống sẽ kiểm tra xem email có trong bảng users hay không, nếu có thì trường hash password trong bảng users sẽ được lấy ra để so sánh với hash password
. Và giá trị của Auth::attempt()
sẽ tra về false hoặc true.
Chúng ta cũng có thể thêm trường thuộc tính vào Auth::attemp()
để xác thực. Ví dụ chúng ta muốn chỉ admin mới được đăng nhập hệ thống
if (Auth::attempt(['email' => $email, 'password' => $password, 'role' => 1])) { // email admin mới được xác thực thành công
}
Chú ý
Ngoài cách sử dụng route('logout')
để logout user ra ngoài khỏi hệ thống thì chúng ta có thể sử dụng Auth::logout()
Ghi nhớ người dùng (Remember me)
Khi mà người dùng request đăng nhập lên hệ thống thì trên server sẽ sinh ra session, đồng thời server sẽ set header trên response trả về client. Mục đích của header này là lưu cookie ở client. Trong cookie sẽ chứa session id tương ứng session trên server. Nhờ đó mà server sẽ biết được ai request ở lần tiếp theo.
Nhưng bạn biết đấy, Cookie thì lâu lâu thì thời gian expire của nó cũng hết, khi đó người dùng sẽ bị logout ra ngoài. Khi chúng ta tích vào ô check box Remember me
khi đăng nhập thì Session ID của người dùng đó sẽ được băm ra rồi lưu trong bảng users tại trường remember_token
, cái này sẽ duy trì đăng nhập lâu dài, user sẽ bị thoát ra ngoài hệ thống khi tự logout thủ công ))
Tiếp nhé, tại sao user lại duy trì đăng nhập lâu dài được khi nhấn vào nút Remember me
. Khi nhấn vào nút dó thì khi server set header thì sẽ set thêm expired date
. Sau khi user tắt browse thì cookie này không bị mất. Mà khi Cookie còn hạn thì sẽ còn tự đăng nhập ))).
4.Kết luận
Bài viết trên mình đã giới thiệu cho các bạn những thứ gì cơ bản nhất về authentication trong Laravel, còn rất nhiều hàm mà Auth
hỗ trợ, các bạn có thể xem trong documentation của nó nhé. Mọi thắc mắc gì hãy comment phía dưới bài viết của mình nhé.