Làm Sao Để Xây Dựng Một Bảo Vệ Xác Thực Trong Laravel

https://code.tutsplus.com/vi/tutorials/how-to-create-a-custom-authentication-guard-in-laravel--cms-29667

Làm Sao Để Xây Dựng Một Bảo Vệ Xác Thực Trong Laravel

by Sajal Soni9 Nov 2017Difficulty:IntermediateLength:LongLanguages:EnglishDeutschEspañolFrançaisBahasa IndonesiaMelayuPусскийTiếng ViệtLaravel 5PHPWeb Development

Vietnamese (Tiếng Việt) translation by Andrea Ho (you can also view the original English article)

Trong bài này, chúng tôi sẽ giới thiệu về hệ thống xác thực trong framework Laravel. Mục đích chính của bài viết này là để tạo ra một bảo vệ xác thực tùy biến bằng cách mở rộng hệ thống xác thực cốt lõi.

Laravel cung cấp một hệ thống xác thực rất vững chắc trong cốt lõi của framework, giúp thực hiện tác vụ xác thực cơ bản một cách dễ dàng. Trong thực tế, bạn chỉ cần chạy một vài lệnh artsan để thiết lập phần khung cơ bản của một hệ thống xác thực.

Hơn nữa, bản thân hệ thống được thiết kế theo cách mà bạn có thể mở rộng nó và gắn kết với những adapter xác thực tự biên của bạn. Đó là những chi tiết chúng ta sẽ thảo luận trong xuyên suốt bài viết này. Trước khi chúng tôi tiếp tục và đào sâu vào việc triển khai của phần bảo vệ xác thực tự biên, chúng ta sẽ bắt đầu với phần thảo luận các yếu tố cơ bản của hệ thống xác thực từ Laravel - guards và providers.

Thành phần cốt lõi: Guard và Provider

Hệ thống xác thực của Laravel được xây dựng từ hai thành phần cốt lõi - guard và provider.

Guards

Bạn có thể nghĩ một guard như một cách cung cấp logic được dùng để xác định người dùng được chứng thực. Trong cốt lõi, Laravel cung cấp nhiều guard khác nhau như session hoặc token. Một session guard duy trì trạng thái của người dùng trong mỗi request bằng cookie, và mặt khác, token guard xác thực người dùng bằng cách kiểm tra một token hợp lệ trong mỗi 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 đó.

Phần sau của bài viết, chúng ta sẽ triển khai một guard để kiểm ra các tham số JSON nhất định trong headers của request và lấy ra người dùng hợp lệ từ MongoDB back-end.Advertisement

Providers

Nếu guard định nghĩa logic của việc chứng thực, thì provider của chứng thực có trách nhiệm lấy ra người dùng từ phần lưu trữ củ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ữ của back-end thì việc triển khai truy xuất người dùng sẽ được chuyển tới provider của việc xác thực.

Laravel mang đến hai provider chứng thực mặc định - Database và Eloquent. Provider của xác thực Database xử lý nhiệm vụ trực tiếp lấy thông tin của người dùng từ bộ lưu trữ ở back-end, còn Eloquent cung cấp một abstraction layer cần thiết để làm việc này.

Trong ví dụ, chúng ta sẽ triển khai một provider xác thực của MongoDB để lấy thông tin người dùng từ back-end của MongoDB.

Vậy đó là giới thiệu cơ bản về guards và providers trong hệ thống xác thực của Laravel. Từ phần tiếp theo trở đi, chúng ta sẽ tập trung vào việc phát triển của bộ bảo vệ chứng thực tự biên và provider!

Sơ lược về Cài đặt File

Hãy lướt nhanh qua danh sách file mà chúng ta sẽ triển khai trong suốt hành trình của bài viết này.

  • config/auth.php: Đây là file cấu hình xác thực mà chúng ta sẽ thêm vào một giá trị của phần bảo vệ của chúng ta.

  • config/mongo.php: Đây là file lưu giữ cấu hình MongoDB.

  • app/Services/Contracts/NosqlServiceInterface.php: Đây là một interface mà class database của Mongo sẽ implement.

  • app/Database/MongoDatabase.php: Đây là một class database để tương tác với MongoDB.

  • app/Models/Auth/User.php: đây là class User model để triển khai Authenticable contract.

  • app/Extensions/MongoUserProvider.php: là phần triển khai của provider của việc xác thực.

  • app/Services/Auth/JsonGuard.php: là phần triển khai của driver của guard của việc xác thực.

  • app/Providers/AuthServiceProvider.php: đây là một file hiện thời chúng tôi sẽ dùng để bổ sung việc gắn kết container của service của chúng ta.

  • app/Http/Controllers/MongoController.php: đây là demo cho file controller mà chúng ta sẽ triển khai để kiểm tra guard tự biên của chúng ta.

Đừng lo lắng nếu danh sách của các file không có rõ ràng khi chúng ta thảo luận mọi thứ chi tiết khi chúng ta xem xét chúng kỹ càng.

Đi sâu vào phần triển khai

Trong phần này, chúng ta sẽ xem kỹ phần triển khai của những file được yêu cầu:

Điều trước tiên chúng ta cần làm là thông báo cho Laravel về guard của chúng ta. Tiếp tục nhập những chi tiết của guard và file config/auth.php như đã hiển thị.

Như bạn đã thấy, chúng ta đã bổ sung guard tự biên vào bên dưới custom key.

Tiếp theo, chúng ta cần nhập bổ sung thông tin của một provider được tương tác trong phần providers.

Chúng ta đã bổ sung provider bên dưới mongo key.

Cuối cùng, hãy thay đổi guard xác thực mặc định từ web sang custom.

Dĩ nhiên nó sẽ chưa hoạt động, khi chúng ta chưa triển khai các file cần thiết. Và đó là điều mà chúng ta sẽ thảo luận trong những phần kế đến.

Cài đặt Driver của MongoDB

Trong phần này, chúng tôi sẽ triển khai các file cần thiết để giao tiếp với giá trị MongoDB.

Đầu tiên hãy tạo một file cấu hình config/mongo.php sẽ lưu những thiết lập kết nối mặc định cho MongoDB.

Dĩ nhiên, bạn cần phải thay đổi các giá trị placeholder theo thiết lập của bạn.

Thay vì trực tiếp tạo một class tương tác với MongoDB, chúng ta sẽ tạo một interface ngay từ đầu.

Lợi ích của việc tạo một interface là nó cung cấp một contract mà mỗi developer cần phải tuân theo trong khi triển khai nó. Đồng thời, triển khai của chúng ta cho MongoDB có thể dễ dàng thay đổi bằng một triển khai NoSQL khác nếu cần thiết.

Tiếp tục và tạo một file interface app/Services/Contracts/NosqlServiceInterface.php với nôi dung như sau:

Đây là một interface khá đơn giản để khai báo các phương thức CRUD mà một class phải định nghĩa khi implement interface này.

Giờ hãy định nghĩa một class thực sự ở app/Database/MongoDatabase.php.

Dĩ nhiên, tôi giả định rằng bạn đã cài đặt MongoDB và extension tương ứng MongoDB của PHP.

Phương thức __construct khởi tạo class MongoClient với các tham số cần thiết. Một phương thức quan trọng khác khiến chúng ta hứng khởi là find, nó sẽ lấy về những giá trị dựa trên thông tin được cung cấp qua các tham số mà phương thức truyền vào.

Vậy đó là quá trình triển khai của driver cho MongoDB, và tôi đã cố gắng tóm gọn nó.

Thiết lập User Model

Tuân thủ các tiêu chuẩn của hệ thống xác thực, chúng ta cần triển khai User Model, nó phải triển khai contract Illuminate\Contracts\Auth\Authenticatable.

Tiếp tục và tạo một file app/Models/Auth/User.php với nội dung dưới đây:

Bạn lẽ ra nên chú ý rằng App\Models\Auth\User đã implement contract Illuminate\Contracts\Auth\Authenticatable.

Đa số các phương thức đã implement class của chúng ta đã tự giải thích. Dù nói như vậy, chúng ta đã định nghĩa phương thức fetchUserByCredentials, nó lấy ra người dùng từ back-end. Trong trường hợp của chúng ta, nó là class MongoDatabase sẽ được gọi để trả về thông tin cần thiết.

Đó là phần triển khai của User Model.

Thiết lập Provider xác thực

Như chúng ta đã thảo luận trước đó, hệ thống xác thực của Laravel gồm có 2 thành phần - guards và providers.

Trong phần này, chúng ta sẽ tạo provider xác thực để xử lý phần lấy người dùng từ back-end.

Tiếp đến tạo một file app/Extensions/MongoUserProvider.php như hiển thị bên dưới.

Lần nữa bạn cần chắc rằng provider tự biên phải implement contract Illuminate\Contracts\Auth\UserProvider.

Tiếp tục, định nghĩa 2 phương thức quan trọng - retrieveByCredentials vả validateCredentials.

Phương thức retrieveByCredentials đươc dùng để lấy thông tin người bằng class User model đã được đề cập trước đó. Mặt khác, phương thức validateCredentials được dùng để xác minh một người dùng với các thông tin đã cung cấp.

Và đó là phần triển khai của provider cho xác thực tự biên của chúng ta. Trong phần tiếp đến, chúng ta sẽ tiếp tục tạo ra một guard để tương tác với provider xác thực MongoUserProvider.

Thiết lập guard xác thực

Nhưng đã thảo luận trước đó, guard trong hệ thống xác thực của Laravel quy định cách user được xác minh thế nào. Trong trường hợp này, chúng ta sẽ kiểm tra sự tồn tại của tham số jsondata trong request, nó nên chứa chuỗi JSON được mã hoá của các thông tin.

Trong phần này, chúng ta sẽ tạo một guard tương tác với provider xác thực vừa được tạo ra trong phần trước đó.

Tiếp tục tạo một file app/Services/Auth/JsonGuard.php với nội dung sau đây:

Trước hết, class của ta cần implement interface Illuminate\Contracts\Auth\Guard. Do đó, chúng ta cần định nghĩa tất cả các phương thức trong interface đó.

Điều quan trọng cần chú ý là hàm __construct yêu cầu một triển khai của Illuminate\Contracts\Auth\UserProvider. Trong trường hợp này, chúng ta sẽ chuyển vào một instance của App\Extensions\MongoUserProvider, chúng ta sẽ thấy trong phần sau đó:

Tiếp theo, một hàm getJsonParams lấy thông tin người dùng từ các tham số của request tên là jsondata. Như mong đợi chúng ta sẽ nhận một chuỗi JSON được mã hoá của thông tin người dùng, chúng ta sẽ dùng hàm json_decode để giải mã dữ liệu JSON.

Trong hàm validate, điều đầu tiên chúng ta kiểm tra là sự tồn tại của tham số $credentials. Nếu nó không hiện diện, chúng ta gọi phương thức getJsonParams để lấy thông tin người dùng từ các tham số trong request.

Tiếp theo, chúng tôi gọi phương thức retrieveByCredentials của provider MongoUserProvider để lấy người dùng từ database MongoDB ở back-end. Cuối cùng, là phương thức validateCredentials của provider MongoUserProvider để kiểm tra tính hợp lệ của User.

Vậy đó là phần triển khai của guard tự biên của chúng ta. Phần tiếp theo mô tả cách kết nối những mảnh ghép lại để tạo thành một hệ thống xác thực hoàn chỉnh.

Kết nối mọi cùng nhau

Cho đến giờ, chúng ta đã phát triển tất cả các yếu tố của guard xác thực, nó sẽ cung cấp cho ta một hệ thống xác thực mới. Tuy nhiên, nó sẽ không hoạt động ngay tức thì vì chúng ta cần phải đăng ký lần đầu bằng việc ràng buộc với Laravel service container.

Như bạn đã biết, Laravel service provider là một nơi để triển khai những ràng buộc cần thiết.

Tiếp tục mở file app/Providers/AuthServiceProvider.php để bổ sung ràng buộc xác thực cho service container. Nếu nó chưa có bất kỳ thay đổi nào, bạn có thể thay thế nó với nội dung sau đây:

Hãy xem kỹ phương thức boot, nó chứa các ràng buộc của provider.

Để bắt đầu, chúng ta sẽ tạo thông tin ràng buộc cho các thành phần App\Database\MongoDatabaseApp\Models\Auth\User.

Đã được một lúc chúng ta nói về provider và guard, và đây là lúc để gắng guard của chúng ta vào hệ thống xác thực của Laravel.

Chúng ta đã dùng phương thức của provider của Facde Auth để bổ sung provider xác thực tự biên bên dưới key mongo. Nhắc lại rằng key này dùng cho xác lập trước đó đã bổ sung trong file auth.php.

Tương tự cách này, chúng ta sẽ chén triển khai cho guard của chúng ta bằng cách dùng phương thức extend của facade Auth.

Tiếp theo, có một phương thức register mà ta đã dùng để gắn kết interface App\Services\Contracts\NosqlServiceInterface đến triển khai App\Database\MongoDatabase.

Vậy bất cứ khi nào có nhu cầu giải quyết dependency App\Services\Contracts\NosqlServiceInterface, Laravel trả lời với triển khai của adapter App\Database\MongoDatabase.

Lợi ích của cách tiếp cận này là có thể dễ dàng thay đổi phần triển khai đã có với một phần triển khai khác. Ví dụ ai đó muốn thay thế triển khai App\Database\MongoDatabase bằng adapter CouchDB trong tương lai. Trong trường hợp đó, họ chỉ cần bổ sung phần kết nối tương tứng trong phương thức register.

Vậy đó là service provider cho cách sắp xếp của bạn. Ở thời điểm này, chúng ta có mọi thứ cần cho để kiểm tra phần triển khai guard tự biên của chúng ta, vậy tiếp theo là những phần nói về việc kiểm tra này.

Nó có hoạt động không?

Bạn đã thực hiện xong những phần khó khăn khi thiết lập guard xác thực tự biên đầu tiên của chúng ta, và giờ là lúc thâu được những ích lợi khi chúng ta sẽ tiếp tục và thử xem sao.

Hãy nhanh chóng triển khai một file controller cơ bản app/Http/Controllers/MongoController.php như bên dưới đây.

Nhìn kỹ vào phần phụ thuộc của phương thức login, nó yêu cầu triển khai của guard Illuminate\Contracts\Auth\Guard. Khi chúng ta thiết lập guard tự biên là guard mặc định trong file auth.php, thực tế là App\Services\Auth\JsonGuard sẽ được đưa vào!

Tiếp đến, chúng ta gọi phương thức validate của class App\Services\Auth\JsonGuard, nó sẽ chuyển thành một loạt việc gọi các phương thức:

  • Nó gọi phương thức retrieveByCredentials của class App\Extensions\MongoUserProvider.

  • Phương thức retrieveByCredentials gọi phương thức fetchUserByCredentials của class App\Models\Auth\User.

  • Phương thức fetchUserByCredentials gọi phương thức find của App\Database\MongoDatabase để lấy thông tin người dùng.

  • Cuối cùng, phương thức find của App\Database\MongoDatabase trả về phản hồi!

Nếu mọi thứ hoạt động như mong đợi, chúng ta sẽ có một người dùng đã được xác thực bằng cách gọi phương thức user của guard của chúng ta.

Để truy xuất controller, bạn nên bổ sung một route trong file routes/web.php.

Hãy thử truy cập URL http://your-laravel-site/custom/mongo/login mà không cần truyền bất kỳ tham số nào và bạn sẽ thấy thông báo "not authorized".

Mặt khác, hãy thử một cái gì đó như http://your-laravel-site/ custom/mongo/login?Jsondata={"username": "admin", "password": "admin"} và nó sẽ trả về một thông báo thành công nếu người dùng hiện hữu trong database của bạn.

Xin lưu ý rằng đây chỉ là cho ví dụ với mục đích chứng minh cách phần guard tự biên hoạt động thế nào. Bạn nên triển khai một giải pháp an toàn hơn cho tính năng như đăng nhập. Trong thực tế, tôi chỉ vừa cung cấp một cái nhìn về quy trình xác thực; bạn có trách nhiệm xây dựng một giải pháp an toàn và mạnh mẽ cho ứng dụng của bạn.

Kết thúc hành trình của chúng ta hôm nay, và hy vọng tôi sẽ trở lại với nhiều điều hữu ích hơn. Nếu bạn muốn tôi viết về một chủ đề cụ thể, đừng quên nhắn tin cho tôi nhé!

Tổng kết

Bản thân Laravel cung cấp một hệ thống xác thực vững chắc, nó có thể được mở rộng nếu bạn muốn triển khai một bản tự xây dựng. Đó là chủ đề ngày hôm nay để xây dựng một guard tự biên và đưa nó vào quy trình xác thực của Laravel.

Trong quá trình đó, chúng tôi đã tiến bước và phát triển một hệ thống xác thực người dùng dựa trên JSON trong yêu cầu và khớp nó với database MongoDB. Và để đạt được điều đó, chúng tôi đã tạo ra một guard tự xây dựng và triển khai một provider tự dựng.

Tôi hy vọng bài tập đã cung cấp cho bạn sự thấu hiểu về quá trình xác thực của Laravel, và bạn nên cảm thấy tự tin hơn về những tác vụ trong đó.

Dành cho những ai vừa bắt đầu với Laravel hoặc tìm kiếm để mở rộng kiến thức của bạn, website hoặc ứng dụng với những phần mở rộng, chúng tôi có nhiều thứ đa dạng bạn có thể học trên Envato Market.

Last updated