Đăng nhập facebook trong cakephp

Xin chào,

Sau đây là hướng dẫn của mình về phần đăng nhập FaceBook trong CakePHP 2.

Mình sẽ tiếp tục sử dụng source code của project Truyện tranh mà mình đã hướng dẫn ở Series Cakephp Framework trên nongdanit.

Điều kiện:

  • Website của bạn.
  • Đăng ký một App trên https://developers.facebook.com/ để lấy được AppID.
  • Tại thời điểm hiện tại của bài viết này Facebook đã thay đổi một số chính sách khắt khe hơn về việc đăng nhập này (https://developers.facebook.com/blog/post/2018/06/08/enforce-https-facebook-login/).
  • Đại khái là nếu các AppID đã được tạo trước tháng 3-2018 thì không bắt buộc HTTPS, nhưng nếu sau thời điểm này thì phải bắt buộc HTTPS mới có thể sử dụng được khi Public App, còn không thì chỉ sử dụng được ở chế độ development(localhost). Và đến 6-10-2018 thì bắt buộc luôn không thể sử dụng HTTP để Login được nữa nếu ai muốn triển khai thì nên lưu ý nhá.

Cách để đăng ký appID thì các bạn tự search trên google nha, mình sẽ sử dụng SDK Javascript để đăng nhập nên chúng ta cần 2 thông số là AppID và version mà bạn muốn sử dụng cho ứng dụng của mình(mình sử dụng v3.1)

Bước 1: Nếu đã đăng ký được ứng dụng của facebook bạn sẽ được như hình dưới đây

Nhớ điền url trang web vào rồi Save lại là được.

Bước 2: quay lại project truyện tranh của chúng ta và tạo layout cho trang login:

Ở routes.php thêm 2 routes để phục vụ cho trang login và logout như sau:


Router::connect('/register.html',array('controller' => 'users', 'action' => 'login'));
Router::connect('/logout',array('controller' => 'users', 'action' => 'logout'));

Ở UsersController.php thêm action login


public function login(){
$this->layout = 'story';
}

Tạo thêm file ngoài view để hiển thị trang login tương ứng với action vừa tạo trên, nội dung các bạn có thể tự tạo, còn làm giống mình thì như sau(hơi dài nhá, vì html mà)


<section class="main-content">
<div class="row">
<div class="span5">
<h4 class="title"><span class="text"><strong>Login</strong> Form</span></h4>
<form action="#" method="post">
<input type="hidden" name="next" value="/">
<fieldset>
<div class="control-group">
<label class="control-label">Username</label>
<div class="controls">
<input type="text" placeholder="Enter your username" id="username" class="input-xlarge">
</div>
</div>
<div class="control-group">
<label class="control-label">Password</label>
<div class="controls">
<input type="password" placeholder="Enter your password" id="password" class="input-xlarge">
</div>
</div>
<div class="control-group">
<input tabindex="3" class="btn btn-inverse large" type="submit" value="Sign into your account">
<a onclick="_login();" class="btn btn-inverse large">Sign into your FaceBook<a>
<hr>
<p class="reset">Recover your <a tabindex="4" href="#" title="Recover your username or password">username or password</a></p>
</div>
</fieldset>
</form>
</div>
<div class="span7">
<h4 class="title"><span class="text"><strong>Register</strong> Form</span></h4>
<form action="#" method="post" class="form-stacked">
<fieldset>
<div class="control-group">
<label class="control-label">Username</label>
<div class="controls">
<input type="text" placeholder="Enter your username" class="input-xlarge">
</div>
</div>
<div class="control-group">
<label class="control-label">Email address:</label>
<div class="controls">
<input type="password" placeholder="Enter your email" class="input-xlarge">
</div>
</div>
<div class="control-group">
<label class="control-label">Password:</label>
<div class="controls">
<input type="password" placeholder="Enter your password" class="input-xlarge">
</div>
</div>
<div class="control-group">
<p>Now that we know who you are. I'm not a mistake! In a comic, you know how you can tell who the arch-villain's going to be?</p>
</div>
<hr>
<div class="actions"><input tabindex="9" class="btn btn-inverse large" type="submit" value="Create your account"></div>
</fieldset>
</form>
</div>
</div>
</section>

<script>

window.fbAsyncInit = function() {
FB.init({
appId : '299035336967208',
cookie : true,
xfbml : true,
version : 'v3.1'
});
FB.AppEvents.logPageView();
FB.getLoginStatus(function(response) {
statusChangeCallback(response);
});
};

(function(d, s, id){
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "https://connect.facebook.net/en_US/sdk.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));

function statusChangeCallback(response) {
if (response.status === 'connected') {console.log('Đã xác thực thành công');} else if (response.status === 'not_authorized') {
console.log('Xác thực chưa thành công');
}
}
function _login() {
FB.login(function(response) {
// Xử lý các kết quả
if(response.status==='connected') {
getFbUserData();
}
}, {scope: 'public_profile,email'});
}
function getFbUserData(){
FB.api('/me', {locale: 'en_US', fields: 'id,first_name,last_name,email,picture'},
function (response) {
saveUserData(response);
});
}
function saveUserData(userData){
$.post(
'/users/loginFB',
{oauth_provider:'facebook',
userData: JSON.stringify(userData)},
function(data){
if(data === false){
alert('Login failed');
}else{
alert('Login success');
}

}
);
}
</script>

Trong đoạn trên phần HTML các bạn chỉ cần chú ý đến: <a onclick=”_login();” class=”btn btn-inverse large”>Sign into your FaceBook<a> Chính là nút để login bằng FB.

Trong thẻ a trên có _login() chính là hàm trong javascript.

Phần javascript như sau:

Đoạn


window.fbAsyncInit = function() {
FB.init({
appId : '299035336957208',
cookie : true,
xfbml : true,
version : 'v3.1'
});
FB.AppEvents.logPageView();
FB.getLoginStatus(function(response) {
statusChangeCallback(response);
});
};

Các bạn thay thế con số  299035336957208 và version thành cái của các bạn nhá.

Các đoạn javascript khác thì các bạn để nguyên. Khi click vào thẻ <a> kia thì hàm _login() được gọi nếu xác thực với facebook thành công sẽ tiếp tục gọi hàm getFbUserData() ở hàm này là chúng ta lấy được các thông tin cần thiết và gọi hàm saveUserData() đẩy những dữ liệu đó qua controller để save vào database.

Bước 3: Quay lại UsersController.php tạo funtion loginFB()


public function loginFB(){
$userData = array();
$this->layout = 'ajax';
$this->autoRender = false;
$dataUserFB = json_decode($_POST['userData']);
if(!empty($dataUserFB)){
$userData['fb_id'] = $dataUserFB->id;
$userData['name'] = $dataUserFB->first_name." ".$dataUserFB->last_name;
$userData['email'] = $dataUserFB->email;
$userData['avatar_face'] = "https://graph.facebook.com/".$userData['fb_id']."/picture?type=large";

$now = date('Y:m:d H:i:s');
$userData['date_created'] = $now;
$userData['date_updated'] = $now;
$userData['group_id'] = 3;
$userDataInsert['User'] = $userData;

$sql = "email like '%$dataUserFB->email%'";
$data = $this->User->find('first', array(
'fields' => array('id','email', 'name'),
'conditions'=>array($sql),
'recursive' =>-1
));
if(!empty($data)){
$this->Session->write('User',$data);
return json_encode($data);
}else{
if($this->User->save($userDataInsert)){
$this->Session->write('User',$userDataInsert);
return json_encode($userData);
}else{
return false;
}
}
}
}

Hàm trên là những cái đơn giản thôi, json_decode mảng truyền qua phương thức post là lấy được dữ liệu, kiểm tra xem email đã tồn tại trong hệ thống hay chưa. Có rồi thì đưa dữ liệu đó vào session, chưa có thì thêm vào database rồi cho vào session.

Thêm một hàm trong UsersController nữa là logout để xoá session đi, và redirect về trang login lại.


function logout(){
$this->Session->delete('User');
$this->redirect('/register.html');
}

đăng nhập facebook trong cakephp
đăng nhập facebook trong cakephp

Và để kiểm tra có đăng nhập thành công hay không các bạn click vào nút Sign into your FaceBook

Nó sẽ hiện ra popup hỏi có cho phép truy cập một số quyền trong lần đầu tiên. Sau khi cho phép sẽ mất popup đi và hiện thông báo như hình:

đăng nhập facebook trong cakephp
đăng nhập facebook trong cakephp

Đây là code trong đoạn javascript cuối cùng, Login success nghĩa là đã đăng nhập thành công và khi đó chúng ta đã có session

Ở đây mình chỉ cho alert() ra thông báo, các bạn có thể có load đến trang nào đó tuỳ theo nhu cầu của chính mình. Và để kiểm tra có user đăng nhập hay chưa thì sử dụng $this->Session->read(‘User’); nếu có dữ liệu nghĩa là đã đăng nhập , chưa có dữ liệu thì chưa được đăng nhập.

Hy vọng các bạn cùng theo dõi với nongdanit

Kết luận

  1. Nếu có thắc mắc gì các bạn để lại comment bên dưới mình sẽ trả lời sớm nhất có thể.
  2. Cảm ơn các bạn đã đọc.

Nongdanit.info
[Cakephp] Đăng nhập website bằng Facebook