Social login with CakePHP
Hiện nay, cùng với sự phát triền không ngừng của các công nghệ thì mạng xã hội cũng không còn xa lạ với đại đa số chúng ta, đặc biệt là những người có sử dụng internet. Việc có một tài khoản Facebook, Google+ hay Twitter đã khá là phổ cập, vậy nên trong các ứng dụng web hay app việc cho phép sử ...
Hiện nay, cùng với sự phát triền không ngừng của các công nghệ thì mạng xã hội cũng không còn xa lạ với đại đa số chúng ta, đặc biệt là những người có sử dụng internet. Việc có một tài khoản Facebook, Google+ hay Twitter đã khá là phổ cập, vậy nên trong các ứng dụng web hay app việc cho phép sử dụng/ tích hợp các tài khoản social trên để login hệ thống cũng đang rất phổ biến. Tôi chưa làm một form login có tính alternative như vậy bao giờ nên cũng đang trong qúa trình tìm hiểu, và tôi đã đọc được một bài viết trên mạng về vấn đề này, cụ thể là sử dụng Facebook OAuth Login. Trong bài viết này tôi sẽ chia sẻ lại nội dung sau khi chỉnh sửa một vài lỗi, bỏ những cái không cần thiết của bài viết đó. Tôi nghĩ có thể sẽ hữu ích với những người đang tìm hiểu social login từ đầu như tôi.
Facebook SDK 4 sẽ yêu cầu phiên bản PHP tối thiểu là 5.4 nên bạn cần upgrade trước nếu đang sử dụng bản cũ hơn.
Đương nhiên điều kiện để bạn sử dụng Facebook là phải có tài khoản, nếu chưa có hãy đăng kí một tài khoản. Sau khi đã có tài khoản thì bạn hãy login vào Facebook developer dành cho các nhà phát triển. Và nếu như bạn chưa là đăng kí với Facebook bạn là một developer thì bạn cần làm việc này trước bằng cách vào menu My Apps chon Register as a Developer.
Sẽ có một popup hiện lên để bạn xác nhận, bạn cần đồng ý (YES) với các điều khoản của Facebook thì mới có thể đăng kí (Register) với tư cách một developer được.
Nếu không có vấn đề xảy ra thì bạn sẽ được thông báo đăng kí thành công, click Done để tiếp tục tạo một App.
Do bạn sẽ tích hợp Facebook vào một ứng dụng web dùng CakePHP nên sẽ chọn Website.
Hãy đặt tên cho App của bạn và click Create New Facebook App ID để tạo ra định danh (ID) cho app đó.
Tiếp theo, bạn sẽ cần chọn xem app của bạn là thuộc nhóm nào, như ở đây tôi chọn Business làm ví dụ và click Create App ID để kết thúc việc tạo app của bạn.
Lúc này bạn click vào app đó thì nó sẽ dẫn tới trang Dashboard của app, bạn cần vào menu Settings > tab Basic để lấy thông tin cần thiết cho việc login. Khi click vào nút Show thì bạn sẽ lấy được App Secret, ngoài ra hãy lưu cả App ID vào đâu đó để sau dùng.
Cuối cùng, bạn cần vào menu Status & Review để công khai app của bạn (đưa Status thành YES như hình dưới), lúc đó app của bạn mới có thể sẵn sàng dùng được.
Để tích hợp được với CakePHP thì bạn cần tải về Facebook PHP SDK, đây là công cụ tạo ra các OAuth request từ ứng dụng của bạn đến Facebook. Tác giả bài viết nguồn sử dụng bản 4.0 nên tôi cũng đã tải nó về từ đây.
Nếu bạn dùng composer thì có thể download qua nó, add khai báo sau vào composer.json { "require" : { "facebook/php-sdk-v4" : "~5.0" } }
Kế đến, bạn gỉai nén ra sẽ được thư mục facebook-php-sdk-v4-4.0-dev, trong này bạn chỉ cần đến thư mục src và file autoload.php. Hãy tạo một thư mục (vd là Facebook) trong thư mục app/Vendor của ứng dụng và copy src + autoload.php vào đó.
Và hãy tạo một file fb_config.php trong thư mục app/Config với nội dung như dưới, mục đích của file này là nơi lưu trữ những hằng cố định trong ứng dụng của bạn. Dòng cuối sẽ gọi đến autoload.php để thực hiện gọi các phương thức cần thiết cho Facebook login.
<?php define('FACEBOOK_LOGIN_SUCCESS', 'Facebook Login Successfully'); define('FACEBOOK_LOGIN_FAILURE', 'Something went wrong !!!'); //base path của web define('BASE_PATH', 'http://localhost/sociallogin/'); //thông tin facebook app define('FACEBOOK_APP_ID', '169068446770578'); // bạn hãy thay XYZ bằng App ID trước đó đã lấy được define('FACEBOOK_APP_SECRET', '4ee33f937e0ed23cb4b3aa70a7b9835f'); // tiếp đó là thay ABC bằng App Secret của bạn define('FACEBOOK_REDIRECT_URI', 'http://localhost/sociallogin/users/fb_login'); define('FACEBOOK_SDK_V4_SRC_DIR','../Vendor/Facebook/src/Facebook/'); require_once(APP . 'Vendor' . DS . 'Facebook' . DS . 'autoload.php'); ?>
Để sử dụng file mới tạo trên, bạn hãy chắc rằng đã inlude nó trong bootstrap.php ở cùng thư mục app/Config :
include_once('fb_config.php');
Tạo Database
Trước tiên, hãy tạo một DB nhỏ cùng với 1 bảng users để lưu trữ các thông tin Facebook trả về. Tôi sẽ lấy về email, first_name, last_name, id, ảnh đại diện nên ít nhất bảng users sẽ cần có các trường đó.
CREATE TABLE `users` ( `id` int(11) NOT NULL AUTO_INCREMENT, `first_name` varchar(60) NOT NULL, `last_name` varchar(60) NOT NULL, `email` varchar(80) NOT NULL, `password` varchar(64) NOT NULL, `social_id` varchar(45) DEFAULT NULL, `picture` varchar(100) DEFAULT NULL, `role` varchar(20) DEFAULT 'author', `created` datetime DEFAULT NULL, `modified` datetime DEFAULT NULL, PRIMARY KEY (`id`), KEY `email_idx` (`email`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
Tạo chức năng login bình thường
Trên cookbook của CakePHP có hướng dẫn làm chức năng login dùng Auth component nên tôi sẽ lược bỏ trình bày về phần này. Bạn có thể đọc trên web về cách làm hoặc xem source code tôi đưa lên Github.
Tôi có chỉnh sửa một chút là tut trên cookbook sử dụng trường username làm tên tài khoản để login mặc định nên tôi đã thay đổi thành email bằng đoạn code sau :
public $components = array( 'Auth' => array( 'authenticate' => array( 'Form' => array( 'fields' => array('username' => 'email') ) ) ) );
Chức năng đã có đầy đủ thêm, sửa, xóa một user, xem list user và login, logout. Việc tiếp theo sẽ là tạo một alternative login sử dụng các tài khoản mạng xã hội, cụ thể bài này là về Facebook.
Facebook login
Tạo nút Facebook login
Tôi đã tìm và sử dụng source trên mạng để làm nút này, bạn có thể down về tại necolas.github.io. Sau khi download về bạn hãy giải nén, copy nội dung file css trong đó và paste vào file cake.generic.css có trong thư mục app/webroot/css. Trong file source down về là dùng cho nhiều tài khoản social có sử dụng chung 1 ảnh auth-icons.png, bạn copy cả file này vào thư mục trên.
Sau đó, hãy thêm đoạn code sau vào login.ctp trong app/View/Users/ để hiển thị ra nút Facebook login :
<fieldset> <legend> <?php echo __('Alternatively, you can :');?> </legend> </fieldset> <a class="btn-auth btn-facebook large" href=<?php echo BASE_PATH.'users/fblogin'; ?>> Log in with <b>Facebook</b></a>
Bạn sẽ có được kế quả như sau
fblogin() và fb_login()
Đây là hai phương thức tác giả đã viết để tạo ra request tới Facebook (fblogin) và nhận kết quả trả về (fb_login), chúng được đặt trong UsersController.php. Tôi không hiểu sao namespace không hoạt động trên bản PHP 5.6 máy tôi đang cài nên đã dùng trực tiếp namespace Facebook trong hai phương thức này, chứ không khai báo trong fb_config.php.
Phương thức fblogin() khởi động session nó chưa có, dùng những thông tin Facebook app của bạn để thực hiện một request login tới Facebook.
public function fblogin() { $this->autoRender = false; if (session_status() == PHP_SESSION_NONE) { session_start(); } FacebookFacebookSession::setDefaultApplication(FACEBOOK_APP_ID, FACEBOOK_APP_SECRET); $helper = new FacebookFacebookRedirectLoginHelper(FACEBOOK_REDIRECT_URI); $url = $helper->getLoginUrl(array('email')); $this->redirect($url); }
Sau đó phương thức fb_login() sẽ tiếp nhận những thông tin trả về để validate, nếu user đã có trong DB bảng users thì sẽ cho login ngay vào hệ thống. Ngược lại, sẽ lưu trữ các thông tin lấy được trước rồi mới để user login thành công và chuyển đến trang index. Phần code khá dài nên bạn hãy tham khảo source code. Bạn sẽ thấy dòng code sau :
$request = new FacebookFacebookRequest($session, 'GET', '/me?fields=first_name,last_name,email');
Khi request tới Facebook, không phải tất cả thông tin của user đều được cung cấp, mặc định là chỉ trả về cho bạn name và id. Đó là lý do nếu theo bài viết gốc, một số người hỏi tại sao không có email trả về. Chúng ta sẽ lấy được những thông tin mà user public, nếu họ không set bảo mật thông tin thì mới lấy được về. Ở đoạn code trên, tôi sẽ thiết lập để chỉ lấy về những thông tin cần thiết.
Cuối cùng, do sử dụng Auth component nên cần cho phép hai phương thức này hoạt động mà chưa cần đến login, bạn sẽ thấy code như sau trong Controller :
public function beforeFilter() { $this->Auth->allow('fblogin', 'fb_login'); if (!$this->Auth->loggedIn()) { $this->Auth->authError = false; } }
Chạy thử
Đến đây, tôi đã hoàn thành việc chuẩn bị các thứ cần thiết để có thể sử dụng tài khoản Facebook login vào hệ thống mà không cần phải tạo, hay nhớ mật khẩu hệ thống nữa. Khi online Facebook là tôi cũng có thể vào các hệ thống khác có cung cấp Social login cho người dùng. Tuy nhiên, để tránh mất các thông tin cá nhân thì bạn nên setting không public chúng trước khi click Login