Bài 3 - Laravel xử lý đăng nhập và phân quyền

Chức năng đăng nhập trong laravel

Chào các bạn, hôm này mình sẽ giới thiệu với các bạn cách tạo trang đăng ký, đăng nhập và phần quyền với Laravel.

Nếu các bạn thực hiện tạo bảng dữ liệu trong mysql bằng cách sử dụng lệnh command "php artisan migrate" thì trong cơ sở dữ liệu của các bạn đã có bảng "users". Nếu trong cơ sở dữ liệu của các bạn chưa có bảng "users" thì các bạn gõ lệnh command trên để laravel sẽ tự động tạo bảng cho các bạn.

Lavarel đã tạo sẵn các file controller cho bảng "users"  trong thư mục "app/Http/Controllers/Auth" nên chúng ta có thể sử dụng các file này để xây dựng chức năng đang nhập.

Trước tiên chúng ta định hướng đường dẫn website mặc định sẽ vào trang đăng nhập cho file web.php trong thư mục routes như sau:

// Sửa đường dẫn trang chủ mặc định
Route::get('/', 'HocsinhController@index');
Route::get('/home', 'HocsinhController@index');

// Đăng ký thành viên
Route::get('register', 'Auth\RegisterController@getRegister');
Route::post('register', 'Auth\RegisterController@postRegister');

// Đăng nhập và xử lý đăng nhập
Route::get('login', [ 'as' => 'login', 'uses' => 'Auth\LoginController@getLogin']);
Route::post('login', [ 'as' => 'login', 'uses' => 'Auth\LoginController@postLogin']);

// Đăng xuất
Route::get('logout', [ 'as' => 'logout', 'uses' => 'Auth\LogoutController@getLogout']);

Tiếp theo, để vào trang học sinh kiểm tra nếu chưa đăng nhập vào hệ thống thì sẽ tự động chuyển ra trang đăng nhập chúng ta thêm đoạn code sau trong file "HocSinhController.php":

public function __construct() {
	$this->middleware('auth');
}

 

Chúng ta sẽ tạo một trang form đăng nhập trong thư mục "resource/views/auth/" file "login.blade.php" với nội dung đoạn code sau:

@extends('templates.master')
@section('title','Trang quản lý')
@section('content')
<?php //Hiển thị thông báo thành công?>
@if ( Session::has('success') )
<div class="alert alert-success alert-dismissible" role="alert">
<strong>{{ Session::get('success') }}</strong>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
<span class="sr-only">Close</span>
</button>
</div>
@endif
<?php //Hiển thị thông báo lỗi?>
@if ( Session::has('error') )
<div class="alert alert-danger alert-dismissible" role="alert">
<strong>{{ Session::get('error') }}</strong>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
<span class="sr-only">Close</span>
</button>
</div>
@endif
@if ($errors->any())
<div class="alert alert-danger alert-dismissible" role="alert">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
<span class="sr-only">Close</span>
</button>
</div>
@endif
<div class="container" style="margin-top: 10%">
<div class="row">
<div class="col-sm-6 col-md-4 col-md-offset-4">
<div class="panel panel-default">
<div class="panel-body">
<form role="form" action="{{ url('/login') }}" method="POST">
{!! csrf_field() !!}
<fieldset>
<div class="row">
<div class="center-block">
<img class="profile-img" src="/public/images/user-icon.png" alt="User">
</div>
</div>
<div class="row">
<div class="col-sm-12 col-md-10 col-md-offset-1 ">
<div class="form-group">
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
<input class="form-control" placeholder="Email" name="email" type="text" value="{{ old('email') }}" autofocus>
</div>
</div>
<div class="form-group">
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-lock"></i></span>
<input class="form-control" placeholder="Mật khẩu" name="password" type="password" value="">
</div>
</div>
<div class="form-group">
<input type="submit" class="btn btn-lg btn-primary btn-block" value="Đăng nhập">
</div>
<div class="login-help">
<a href="/{{ url('/register') }}" >Đăng ký</a> - <a href="#" >Quên mật khẩu</a>
</div>
</div>
</div>
</fieldset>
</form>
</div>
</div>
</div>
</div>
</div>
<style>
body{
background: #17568C;
}
.panel{
border-radius: 5px;
}
.panel-heading {
padding: 10px 15px;
}
.panel-title{
text-align: center;
font-size: 15px;
font-weight: bold;
color: #17568C;
}
.panel-footer {
padding: 1px 15px;
color: #A0A0A0;
}
.profile-img {
width: 120px;
height: 120px;
margin: 0 auto 10px;
display: block;
-moz-border-radius: 50%;
-webkit-border-radius: 50%;
border-radius: 50%;
}
</style>
@endsection

 

Trong file web.php chúng ta đã định trang đang nhập bằng cách gọi hàm "getLogin()" trong file "LoginController.php".

Vậy nên chúng ta sẽ viết hàm hiển thị form đăng nhập trong "LoginController.php" của thư mục "app/Http/Controllers/Auth" để gọi đến file form chúng ta đã tạo.

public function getLogin() {
	return view('auth/login');
}

Tiếp theo chúng ta sẽ viết thêm hàm xử lý đăng nhập trong "LoginController.php" của thư mục "app/Http/Controllers/Auth". Chúng ta cần khai báo một số thư viện được sử dụng trong hàm xử lý.

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Auth;
use Session;

Nội dung hàm xử lý đăng nhập:

public function postLogin(Request $request) {
	// Kiểm tra dữ liệu nhập vào
	$rules = [
		'email' =>'required|email',
		'password' => 'required|min:6'
	];
	$messages = [
		'email.required' => 'Email là trường bắt buộc',
		'email.email' => 'Email không đúng định dạng',
		'password.required' => 'Mật khẩu là trường bắt buộc',
		'password.min' => 'Mật khẩu phải chứa ít nhất 8 ký tự',
	];
	$validator = Validator::make($request->all(), $rules, $messages);
	
	
	if ($validator->fails()) {
		// Điều kiện dữ liệu không hợp lệ sẽ chuyển về trang đăng nhập và thông báo lỗi
		return redirect('login')->withErrors($validator)->withInput();
	} else {
		// Nếu dữ liệu hợp lệ sẽ kiểm tra trong csdl
		$email = $request->input('email');
		$password = $request->input('password');

		if( Auth::attempt(['email' => $email, 'password' =>$password])) {
			// Kiểm tra đúng email và mật khẩu sẽ chuyển trang
			return redirect('hocsinh');
		} else {
			// Kiểm tra không đúng sẽ hiển thị thông báo lỗi
			Session::flash('error', 'Email hoặc mật khẩu không đúng!');
			return redirect('login');
		}
	}
}

Đến đây chức năng đăng nhập đã hoàn thành. Vì cơ sở dữ liệu được tạo không có tài khoản nào nên chúng ta sẽ viết tiếp form đăng ký thành viên.

Chúng ta sẽ viết form đăng ký thành viên trong thư mục "resources/views/auth" tên file là "register.blade.php" với nội dung đoạn code như sau:

@extends('templates.master')
@section('title','Trang quản lý')
@section('content')
<?php //Hiển thị thông báo thành công?>
@if ( Session::has('success') )
<div class="alert alert-success alert-dismissible" role="alert">
<strong>{{ Session::get('success') }}</strong>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
<span class="sr-only">Close</span>
</button>
</div>
@endif
<?php //Hiển thị thông báo lỗi?>
@if ( Session::has('error') )
<div class="alert alert-danger alert-dismissible" role="alert">
<strong>{{ Session::get('error') }}</strong>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
<span class="sr-only">Close</span>
</button>
</div>
@endif
@if ($errors->any())
<div class="alert alert-danger alert-dismissible" role="alert">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
<span class="sr-only">Close</span>
</button>
</div>
@endif
<div class="container" style="margin-top: 10%">
<div class="row">
<div class="col-sm-6 col-md-4 col-md-offset-4">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">ĐĂNG KÝ THÀNH VIÊN</h4>
</div>
<div class="panel-body">
<form role="form" method="POST" action="{{ url('/register') }}">
{!! csrf_field() !!}
<div class="form-group">
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
<input class="form-control" placeholder="Họ và tên" name="name" type="text" value="{{ old('name') }}" autofocus>
</div>
</div>
<div class="form-group">
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-envelope"></i></span>
<input class="form-control" placeholder="Email" name="email" type="text" value="{{ old('email') }}">
</div>
</div>
<div class="form-group">
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-lock"></i></span>
<input class="form-control" placeholder="Mật khẩu" name="password" type="password">
</div>
</div>
<div class="form-group">
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-lock"></i></span>
<input class="form-control" placeholder="Xác nhận mật khẩu" name="password_confirmation" type="password">
</div>
</div>
<div class="form-group">
<button type="submit" class="btn btn-lg btn-primary btn-block">Đăng ký</button>
</div>
<center><a href="/{{ url('/login') }}">Quay về đăng nhập</a></center>
</form>
</div>
</div>
</div>
</div>
</div>
<style>
body{
background: #17568C;
}
.panel{
border-radius: 5px;
}
.panel-heading {
padding: 10px 15px;
}
.panel-title{
text-align: center;
font-size: 15px;
font-weight: bold;
color: #17568C;
}
.panel-footer {
padding: 1px 15px;
color: #A0A0A0;
}
.profile-img {
width: 120px;
height: 120px;
margin: 0 auto 10px;
display: block;
-moz-border-radius: 50%;
-webkit-border-radius: 50%;
border-radius: 50%;
}
</style>
@endsection

Trong file web.php chúng ta đã viết chức năng gọi đến đường dẫn đăng ký thành viên bằng cách gọi đến hàm getRegister() trong file "RegisterController.php" của thư mục "app/Http/Controllers/Auth" nên chúng ta sẽ viết hàm này gọi đến form đăng ký như sau:

public function getRegister() {
	return view('auth/register');
}

Tiếp theo chúng ta sẽ khai báo một số thư viện sau cho hàm hàm xử lý đăng ký như sau:

use Illuminate\Http\Request;
use Session;

Nội dung code hàm xử lý đăng ký trong file "RegisterController.php" sẽ được viết như sau:

public function postRegister(Request $request) {
    // Kiểm tra dữ liệu vào
	$allRequest  = $request->all();	
	$validator = $this->validator($allRequest);

	if ($validator->fails()) {
		// Dữ liệu vào không thỏa điều kiện sẽ thông báo lỗi
		return redirect('register')->withErrors($validator)->withInput();
	} else {   
		// Dữ liệu vào hợp lệ sẽ thực hiện tạo người dùng dưới csdl
		if( $this->create($allRequest)) {
			// Insert thành công sẽ hiển thị thông báo
			Session::flash('success', 'Đăng ký thành viên thành công!');
			return redirect('register');
		} else {
			// Insert thất bại sẽ hiển thị thông báo lỗi
			Session::flash('error', 'Đăng ký thành viên thất bại!');
			return redirect('register');
		}
	}
}

Trong đoạn code trên chúng ta sử dụng hàm kiểm tra dữ liệu nhập vào validator(), các bạn có thể chỉnh nội dung thông báo thành tiếng việt bằng cách thay đổi thành đoạn code 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',
		],
		[
			'name.required' => 'Họ và tên là trường bắt buộc',
			'name.max' => 'Họ và tên không quá 255 ký tự',
			'email.required' => 'Email là trường bắt buộc',
			'email.email' => 'Email không đúng định dạng',
			'email.max' => 'Email không quá 255 ký tự',
			'email.unique' => 'Email đã tồn tại',
			'password.required' => 'Mật khẩu là trường bắt buộc',
			'password.min' => 'Mật khẩu phải chứa ít nhất 8 ký tự',
			'password.confirmed' => 'Xác nhận mật khẩu không đúng',
		]
	);
}

 

Đên đây các bạn có thể tạo một tài khoản và đăng nhập vào hệ thống. Nếu các bạn muốn phân quyền người dụng các bạn có thể thực hiện như sau:

+ Thêm một trường dữ liệu vào bảng "user" có tên là "level" miền giá trị kiểu int(10): Trường này chúng ta quy định 1 là SuperAdmin, 2 là Admin, 3 là thành viên.

+ Sửa lại hàm create() trong file "RegisterController.php" chúng ta thêm giá trị cho trường level như đoạn code sau:

protected function create(array $data)
{
	return User::create([
		'name' => $data['name'],
		'email' => $data['email'],
		'level' => '3',
		'password' => bcrypt($data['password']),
	]);
}

+  Chúng ta thêm level cho "protected $fillable " trong file "User.php" của thư mục "app" như sau:

protected $fillable = [
	'name', 'email', 'password', 'level',
];

Khi đăng ký thành viên thì level sẽ là 3 (thành viên). Chúng ta có thể hiển thị kết quả phân quyền bằng các thêm đoạn code sau trong thẻ <div class="container"></div> của file master.blade.php

@if (Auth::check())
<div>
Bạn đang đăng nhập với quyền 
@if( Auth::user()->level == 1)
	{{ "SuperAdmin" }}
@elseif( Auth::user()->level == 2)
	{{ "Admin" }}
@elseif( Auth::user()->level == 3)
	{{ "Thành viên" }}
@endif
</div>
<div class="pull-right" style="margin-top: 3px;"><a class="btn btn-primary" href="/{{ url('/logout') }}">Đăng xuất</a></div>
@endif

Trong đoạn code trên tôi có thêm nút đăng xuất và trong file web.php cũng đã tạo link đăng xuất gọi đến hàm getLogout() trong file "LogoutController.php".

Chúng ta sẽ tạo file "LogoutController.php" bằng cách gõ lệnh command sau:

php artisan make:controller Auth/LogoutController --resource

Sau khi tạo xong chúng ta vào thư mục mở file "LogoutController.php" và viết nội dung file với nội dung như sau:

<?php

namespace App\Http\Controllers\Auth;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;

class LogoutController extends Controller
{
    public function __construct() {
    	$this->middleware('auth');
    }
		
	public function getLogout() {
		Auth::logout();
		return redirect('login');
	}
}

 

Vậy là chúng ta đã hoàn thành các chức năng đăng ký, đăng nhập, phân quyền và đăng xuất.

Qua bài này, mong là có thể giúp ích cho các bạn trong lập trình php với laravel.

Ngụy kim Hưng