เนื้อหาตอนต่อไปนี้ เราจะมาดูในส่วนของรูปแบบการใช้งาน
การเชื่อมโยงบัญชีผู้ใช้ หรือระบบสมาชิกเดิมของเราที่มีอยู่แล้ว
กับบัญชี Social ซึ่งต่อเนื่องจากตอนที่ 3 ทบทวนตอนที่แล้วได้ที่บทความ
การใช้งาน Social Login ร่วมกับระบบสมาขิก อัพเดทปี 2020 ตอนที่ 3 http://niik.in/988
การเชื่อมโยงบัญชีผู้ใช้ กับระบบสมาชิกเดิม
การเชื่อมบัญชีผู้ใช้ social กับระบบสมาชิก อย่างที่ได้อธิบายไปบ้างแล้วในตอนที่ผ่านมา เราจะต้องมีฟิลด์
ข้อมูลหนึ่งสำหรับเชื่อมโยงความสัมพันธ์ระหว่างระบบสมาชิกเดิมที่มีอยู่แล้ว กับข้อมูลบัญชี social ที่เราจะ
ทำการเชื่อมโยง สมมติเช่น เรามีระบบสมาชิก และมีผู้ใช้งานที่กำลังอยู่ในระบบด้วย user_id เท่ากับ 1234 และ
เราต้องการให้ผู้ใช้คนนี้ สามารถเชื่อมกับบัญชี social ใดๆ ก็ได้ เพื่อใช้เป็นทางเลือกในการล็อกอินเข้าใช้งาน
นั่นคือ ผู้คนนี้ ก็จะเชื่อมกันระหว่าง user_id 1234 กับ Line id, google id , facebook id หรือ twitter id อย่างใดอย่างหนึ่ง
หรือทั้งหมดก็ได้ ในที่นี้เราจะใช้ตารางที่ชื่อ tbl_social ลองดูตัวอย่างการเชื่อมตารางดังรูปด้านล่าง
tbl_user user_id name email picture 1234 user1 user1@gmail.com user1.png 5678 user2 user2@gmail.com user2.png
tbl_social social_id link_user_id social_user_id 1 1234 line id 2 1234 google id 3 5678 facebook id2 4 1234 facebook id 5 1234 twitter id
เมื่อทำการเชื่อมบัญชี social เราก็จะทำการเพิ่มข้อมูลใหม่เข้าไปในตาราง tbl_social โดยใช้ user_id ที่กำลังใช้งานอยู่ เป็น link_user_id
และบันทึก social_user_id ที่ต้องการเชื่อมโยง
ดังนั้น ในขั้นตอนล็อกอิน หลังจากมีการเชื่อมโยงแล้ว เราก็สามารถดึงข้อมูลของผู้ใช้ในตาราง tbl_user ที่สัมพันธ์กับ social_user_id
ที่ได้ทำการเชื่อมโยงในตาราง tbl_socail ไว้แล้วได้นั่นเอง
แน่นอนว่า การเชื่อมโยงบัญชี เราจะทำตอนที่ผู้ใช้ล็อกอินอยู่ในระบบเดิม และทำการเปิดใช้งานการเชื่อมโยงกับบัญชี social ที่ต้องการ แล้วถ้ากรณี
ที่เป็นผู้ใช้ใหม่ ยังไม่มีบัญชีการใช้งานใดๆ เลย เราจะทำได้อย่างไรบ้าง กับเงื่อนไขกรณีแบบนี้ สามารถทำได้หลายวิธี ขึ้นกับว่าเราต้องการใช้
วิธีแบบไหน เช่น หากยังไม่มีเคยมีบัญชีสมาชิกในระบบเลย แต่ต้องการล็อกอินด้วย line เราอาจจะลิ้งค์ไปยังหน้าสมัครสมาชิกของเราปกติก่อน นั่นคือ
ผู้ใช้คนนั้น ต้องสมัครสมาชิกโดยระบบปกติก่อน แล้วถึงจะสามารถไปเปิดการเชื่อมโยงกับบัญชี line ได้ และอีกวิธีหนึ่ง หากยังไม่เคยมีบัญชีสมาชิกใน
ระบบเลย แต่ต้องการล็อกอินด้วย line เราสามารถใช้ข้อมูลในบัญชี line ทำการสร้างบัญชีผู้ใช้ในระบบปกติ โดยใช้ข้อมูลเบี้องต้น เช่น ชื่อ หรือ
อีเมล หรือรูปโพรไฟล์ พร้อมทั้งสร้างการเชื่อมโยงบัญชี socail ไปพร้อมๆ กัน กล่าวคือ เมื่อล็อกอินด้วยบัญชี line ให้เพิ่มข้อมูลในตาราง tbl_user
เราก็จะได้ user_id ในขั้นตอนนี้ จากนั้นก็เพิ่มข้อมูลในตาราง tbl_social โดยใช้ user_id ที่เพิ่งสร้าง มาใช้ในการเชื่อมบัญชี
ถ้าเราสังเกตตามรูปแบบการใช้งาน จะเห็นวิธีที่สอง จะเป็นวิธีที่สะดวกสำหรับผู้ใช้งาน เพราะสามารถล็อกอินด้วยบัญชี line พร้อมทั้งสร้างบัญชีผู้
ใช้ใหม่ในระบบไปพร้อมๆ กัน แต่ก็ยังมีข้อควรเข้าใจสิ่งหนึ่งว่า ถ้าผู้ใช้คนนั้นเคยมีบัญชีผู้ใช้ในระบบอยู่แล้ว และยังไม่เคยผูกบัญชี line แต่ต้องการ
ล็อกอินผ่าน line กรณีนี้ จะกลายเป็นว่า ผู้ใช้ได้สร้างบัญชีใหม่ขึ้นมาพร้อมกับเชื่อมกับบัญชี line นั่นเอง
อย่างไรก็ตาม ในที่นี้ เราจะเลือกวิธีที่เห็นว่าเหมาะสมที่สุด นั่นคือ หากยังไม่เคยมีบัญชีใดๆ เลย ถ้าเลือกล็อกอินด้วย social เราจะทำการสร้างบัญชี
ผู้ใช้ใหม่ พร้อมเชื่อมกับบัญชี social และล็อกอินเข้าใช้งาน และกรณีล็อกอินเข้าใช้งานอยู่แล้ว ผู้ใช้สามารถที่จะเลือกเชื่อมกับบัญชี socical ใดๆ ตาม
ต้องการ และสามารถที่จะยกเลิการเชื่อมบัญชี social นั้นๆ ได้
โครงสร้างตารางสมาชิกหลัก ที่มีอยู่แล้ว tbl_user
ตารางนี้ ไม่จำเป็นต้องเหมือนกับตัวอย่าง เป็นตารางสมาชิกเดิมที่เรามีอยู่แล้ว หลักๆ ควรมี id กับ name ในที่นี้ ฟิลด์ที่ใช้งานและสัมพันธ์กับการ
ทดสอบประกอบด้วย id name email picture และ last_login
-- -- Table structure for table `tbl_user` -- CREATE TABLE `tbl_user` ( `id` int(11) NOT NULL, `name` varchar(100) NOT NULL, `email` varchar(100) NOT NULL, `picture` varchar(100) NOT NULL, `create_date` timestamp NOT NULL DEFAULT current_timestamp(), `last_login` datetime NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- -- Indexes for dumped tables -- -- -- Indexes for table `tbl_user` -- ALTER TABLE `tbl_user` ADD PRIMARY KEY (`id`); -- -- AUTO_INCREMENT for dumped tables -- -- -- AUTO_INCREMENT for table `tbl_user` -- ALTER TABLE `tbl_user` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; COMMIT;
ต่อไปเป็นส่วนของตาราง tbl_social สำหรับเชื่อมบัญชี social
-- -- Table structure for table `tbl_social` -- CREATE TABLE `tbl_social` ( `social_id` int(11) NOT NULL, `user_id` int(11) NOT NULL, `name` varchar(100) NOT NULL, `email` varchar(100) NOT NULL, `picture` varchar(100) NOT NULL, `social_token` varchar(255) NOT NULL, `create_date` timestamp NOT NULL DEFAULT current_timestamp(), `last_login` datetime NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- -- Indexes for dumped tables -- -- -- Indexes for table `tbl_social` -- ALTER TABLE `tbl_social` ADD PRIMARY KEY (`social_id`); -- -- AUTO_INCREMENT for dumped tables -- -- -- AUTO_INCREMENT for table `tbl_social` -- ALTER TABLE `tbl_social` MODIFY `social_id` int(11) NOT NULL AUTO_INCREMENT; COMMIT;
ต่อด้วยส่วนของไฟล์ User Class ที่จะจัดการทุกอย่างเกี่ยวกับข้อมูลการเชื่อมโยง มีการปรับโค้ดเพิ่มเติมจากตอนที่ 3
เพื่อให้สอดคล้องกับการใช้งาน
ไฟล์ User.php
<?php class User{ // $salt สามารถใช้คำสั่ง password_hash("mysslweb",PASSWORD_BCRYPT); สร้างได้ private $_SALT = '$2y$10$cDKiRAzt3zWwiyAu/Nz40Om6yKe1mQZMM4T6yxAlTTI25oIUq9EVm'; private $_USER_DATA; private $_SOCIAL_TYPE; private $_DB; private $_SESS_USER_ID; public function __construct($db, $userData, $socialType){ $this->_DB = $db; // รับค่า mysqli สำหรับจัดการฐานข้อมูล $this->_USER_DATA = $userData; $this->_SOCIAL_TYPE = $socialType; // ตรวจสอบ และกำหนดตัวแปร session if(isset($_SESSION['ses_user_id']) && !empty($_SESSION['ses_user_id'])){ $this->_SESS_USER_ID = $_SESSION['ses_user_id']; } } public function login(){ // จัดรูปแบบ Tokken ที่จะบันทึกลงฐานข้อมูล $checkToken = md5(sprintf("%02d",$this->_SOCIAL_TYPE))."|".$this->_USER_DATA['token']; $result = $this->_DB->query(" SELECT a.*, b.social_id FROM tbl_user a LEFT JOIN tbl_social b ON a.id=b.user_id WHERE b.social_token='{$checkToken}' "); if($result && $result->num_rows>0){ // มีในระบบแล้ว $row = $result->fetch_assoc(); $success_connected = true; // เมื่อล็อกอินอยู่ if(!is_null($this->_SESS_USER_ID)){ if($this->_SESS_USER_ID!=$row['id']){ // ถูกเชื่อมไปกับบัญชีคนอื่นแล้ว $success_connected = false; } } if($success_connected==true){ // กำหนด session ที่จะใช้งานในระบบเรา $_SESSION['ses_user_id'] = $row['id']; $_SESSION['ses_user_name'] = $row['name']; $_SESSION['ses_user_email'] = $row['email']; $_SESSION['ses_user_picture'] = $row['picture']; $last_login = date("Y-m-d H:i:s"); // อัพเดทเวลาเข้าใช้ล่าสุดในตารางหลัก tbl_user $this->_DB->query(" UPDATE tbl_user SET last_login='{$last_login}' WHERE id='{$row['id']}' "); // อัพเดทเวลาเข้าใช้ล่าสุดในตาราง tbl_social $this->_DB->query(" UPDATE tbl_social SET last_login='{$last_login}' WHERE social_id='{$row['social_id']}' "); } }else{ // ยังไม่มีในระบบ หรือยังไม่เชื่อมต่อบัญชี สมัครสมาชิก หรือเชื่อมต่อบัญชีผู้ใช้ $this->register($checkToken); } } public function disconnect(){ // ยกเลิกการเชื่อมบัญชี ทำได้กรณีต้องล็อกอินเท่านั้น if(!is_null($this->_SESS_USER_ID)){ // ค่าสำหรับตรวจสอบประเภท social ที่ใช้งานอยู่ $socialCheck = md5(sprintf("%02d",$this->_SOCIAL_TYPE)); $result = $this->_DB->query(" SELECT a.*, b.social_id,b.picture as social_picture FROM tbl_user a LEFT JOIN tbl_social b ON a.id=b.user_id WHERE b.user_id='{$this->_SESS_USER_ID}' AND b.social_token LIKE '{$socialCheck}%' "); if($result && $result->num_rows>0){ // มีเราระบบแล้ว $row = $result->fetch_assoc(); if($row['picture']!=$row['social_picture']){ // ถ้ารูปไม่ถูกใช้ในรูปหลัก @unlink("../avatar/{$row['social_picture']}"); // ลบรูปของบัญชี social นี้ } // ลบข้อมูลบัญชี social ที่เชื่อมต่อ $this->_DB->query("DELETE FROM tbl_social WHERE social_id='{$row['social_id']}' "); } } } public function getuser($id){ $result = $this->_DB->query("SELECT * FROM tbl_user WHERE id='{$id}' "); if($result && $result->num_rows>0){ $row = $result->fetch_assoc(); return $row; }else{ return; } } public function register($token){ if(is_null($this->_SESS_USER_ID)){ // ไม่ได้ล็อกอินอยู่ หรือเป็นสมาชิกใหม่ // เพิ่มข้อมูลบัญชีผู้ใช้ใหม่ในระบบสมาชิก $result = $this->_DB->query(" INSERT INTO tbl_user SET name='{$this->_USER_DATA['name']}', email='{$this->_USER_DATA['email']}' "); if($result && $this->_DB->affected_rows>0){ $insert_userID = $this->_DB->insert_id; // ลำดับ id ที่เพิ่มล่าสุด // นำลำดับ id ที่เพิ่มล่าสุดมาจัดรูปแบบ เพื่อสร้าง user_picture_id ไว้ใช้เป็นชื่อรูปของบัญชี social นั้นๆ $user_picture_id = $this->removespecialchar(crypt(sprintf("%07d",$insert_userID.time()),$this->_SALT)); // บันทึกรูปจาด url สร้างรูป avatar ใน servr ของเรา $avatar = $this->saveavatar($this->_USER_DATA['picture'],$user_picture_id); $last_login = date("Y-m-d H:i:s"); // เพิ่มข้อมูลตารางเชื่อมโยงบัญชี social tbl_social $this->_DB->query(" INSERT INTO tbl_social SET user_id='{$insert_userID}', name='{$this->_USER_DATA['name']}', email='{$this->_USER_DATA['email']}', picture='{$avatar}', social_token='{$token}', last_login='{$last_login}' "); // อัพเดทข้อมูลบัญชีสมาชิกเพิ่มเติม $this->_DB->query(" UPDATE tbl_user SET picture='{$avatar}', last_login='{$last_login}' WHERE id='{$insert_userID}' "); // ดึงข้อมูลสมาชิก กรณีสมัคสมาชิกใหม่ $row = $this->getuser($insert_userID); if(isset($row)){ // กำหนด session ที่จะใช้งานในระบบเรา $_SESSION['ses_user_id'] = $row['id']; $_SESSION['ses_user_name'] = $row['name']; $_SESSION['ses_user_email'] = $row['email']; $_SESSION['ses_user_picture'] = $row['picture']; } } }else{ // กรณีที่ล็อกอินใช้งานในระบบอยู่ และจะเชื่อมบัญชี social $insert_userID = $this->_SESS_USER_ID; // ใช้ session id ของผู้ใช้ปัจจุบัน // นำ session user id เพื่อสร้าง user_picture_id ไว้ใช้เป็นชื่อรูปของบัญชี social นั้นๆ $user_picture_id = $this->removespecialchar(crypt(sprintf("%07d",$insert_userID.time()),$this->_SALT)); // บันทึกรูปจาด url สร้างรูป avatar ใน servr ของเรา $avatar = $this->saveavatar($this->_USER_DATA['picture'],$user_picture_id); $last_login = date("Y-m-d H:i:s"); // เพิ่มข้อมูลตารางเชื่อมโยงบัญชี social tbl_social $this->_DB->query(" INSERT INTO tbl_social SET user_id='{$insert_userID}', name='{$this->_USER_DATA['name']}', email='{$this->_USER_DATA['email']}', picture='{$avatar}', social_token='{$token}', last_login='{$last_login}' "); // อัพเดทข้อมูลบัญชีสมาชิกเพิ่มเติม ใช้รูปจาก social นี้ถ้า รูปในฟิลด์หลักเป็นค่าว่าง $this->_DB->query(" UPDATE tbl_user SET picture='{$avatar}', last_login='{$last_login}' WHERE id='{$insert_userID}' AND picture='' "); // อัพเดทข้อมูลบัญชีสมาชิกเพิ่มเติม ใช้อีเมลจาก social นี้ถ้า อีเมลในฟิลด์หลักเป็นค่าว่าง $this->_DB->query(" UPDATE tbl_user SET email='{$this->_USER_DATA['email']}' WHERE id='{$insert_userID}' AND email='' "); // อัพเดทข้อมูลบัญชีสมาชิกเพิ่มเติม $this->_DB->query(" UPDATE tbl_user SET last_login='{$last_login}' WHERE id='{$insert_userID}' "); // ดึงข้อมูลสมาชิก กรณีสมัคสมาชิกใหม่ $row = $this->getuser($insert_userID); if(isset($row)){ // กำหนด session ที่จะใช้งานในระบบเรา $_SESSION['ses_user_id'] = $row['id']; $_SESSION['ses_user_name'] = $row['name']; $_SESSION['ses_user_email'] = $row['email']; $_SESSION['ses_user_picture'] = $row['picture']; } } } public function removespecialchar($value){ return preg_replace('/[^a-zA-Z0-9_ -]/s','',$value); } public function saveavatar($picture_url,$user_id){ $imgExt = array("1"=>".gif", "2"=>".jpg", "3"=>".png"); $imgType = exif_imagetype($picture_url); $avatar_filename = ""; try{ $endpontURL = $picture_url; $ch = curl_init(); curl_setopt( $ch, CURLOPT_URL, $endpontURL); curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1); $result = curl_exec( $ch ); $avatar_filename = "{$user_id}".$imgExt[$imgType]; $filePath = "../avatar/{$avatar_filename}"; // บันทึกรูปไว้ที่โฟลเดอร์ avatar file_put_contents($filePath,$result); }finally{ curl_close( $ch ); } return $avatar_filename; } }
ก่อนที่เราจะไปดูต่อสำหรับโค้ดแต่ละ platform ซึ่งเพิ่มขึ้นมาเล็กน้อย จะขอพูด DEMO การทำงาน
อย่างที่เกริ่นไป การทำงานของระบบของเรา รองรับการสร้างบัญชีผู้ใช้ใหม่ด้วยการล็อกอินผ่าน soical และรองรับการเชื่อมโยงบัญชีกรณีเป็นสมาชิก
อยู่แล้ว ดังนั้น การจำลอง DEMO ของเรา จะเริ่มต้นด้วย การล็อกอิน และสร้างบัญชีผู้ใช้ใหม่ และเมื่อเราอยู่ในระบบเรียบร้อยแล้ว ก็จะเป็นการจำลอง
การเชื่อมบัญชี กรณีเป็นสมาชิกอยู่แล้วนั่นเอง
ดังนั้น เราจะมาปรับหน้าตาการแสดงผลของหน้า member ในลักษณะผลลัพธ์ ดังนี้
ไฟล์ member.php
<?php session_start(); // โค้ดไฟล์ dbconnect.php ดูได้ที่ http://niik.in/que_2398_5642 require_once("dbconnect.php"); if(!isset($_SESSION['ses_user_id']) || empty($_SESSION['ses_user_id'])){ header("Location:login.php"); exit; } // บัญชี social ที่ผู้ใช้เชื่อมการใช้งานอยู่ $arr_connect = array(); $sql = " SELECT social_token FROM tbl_social WHERE user_id='{$_SESSION['ses_user_id']}' "; $result = $mysqli->query($sql); if($result && $result->num_rows>0){ // คิวรี่ข้อมูลสำเร็จหรือไม่ และมีรายการข้อมูลหรือไม่ while($row = $result->fetch_assoc()){ // วนลูปแสดงรายการ list($social_type) = explode("|",$row['social_token']); $arr_connect[] = $social_type; } } ?> <!DOCTYPE html> <html lang='en'> <head> <meta charset='utf-8' /> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta http-equiv="Content-Security-Policy" content="block-all-mixed-content"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.12.0-2/css/all.min.css"> <title>Document</title> </head> <body> <div class="mx-auto mt-5" style="width: 500px;"> <h1>MEMBER</h1> <ul class="nav justify-content-center"> <li class="nav-item"> <a class="nav-link active" href="index.php">Home</a> </li> <li class="nav-item"> <a class="nav-link" href="login.php">Login</a> </li> <li class="nav-item"> <a class="nav-link" href="member.php">Member</a> </li> <li class="nav-item"> <a class="nav-link" href="logout.php">Logout</a> </li> </ul> <div> <h4><?=$_SESSION['ses_user_name']?></h4> <img src="avatar/<?=$_SESSION['ses_user_picture']?>" style="width: 50px;"> </div> <style type="text/css"> .text-facebook{ color:#087CEA !important;} .text-line{ color: #00B900 !important;} .text-google{ color: #FF0000 !important;} .text-twitter{ color: #1DA1F3 !important;} .toggle { cursor: pointer; display: inline-block; margin-bottom: 0; } .toggle-switch { display: inline-block; background: #ccc; border-radius: 16px; width: 58px; height: 32px; position: relative; vertical-align: middle; transition: background 0.25s; } .toggle-switch:before, .toggle-switch:after { content: ""; } .toggle-switch:before { display: block; background: linear-gradient(to bottom, #fff 0%, #eee 100%); border-radius: 50%; box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25); width: 24px; height: 24px; position: absolute; top: 4px; left: 4px; transition: left 0.25s; } .toggle:hover .toggle-switch:before { background: linear-gradient(to bottom, #fff 0%, #fff 100%); box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.5); } .toggle-checkbox:checked + .toggle-switch { background: #0061f2; } .toggle-checkbox:checked + .toggle-switch.app-line { background: #00B900 !important; } .toggle-checkbox:checked + .toggle-switch.app-facebook { background: #087CEA !important; } .toggle-checkbox:checked + .toggle-switch.app-google { background: #FF0000 !important; } .toggle-checkbox:checked + .toggle-switch.app-twitter { background: #1DA1F3 !important; } .toggle-checkbox:checked + .toggle-switch:before { left: 30px; } .toggle-checkbox { position: absolute; visibility: hidden; } .toggle-label { margin-left: 5px; position: relative; top: 2px; } </style> <div class="card-body"> <?php $platforms = array( array( "id" => 1, "name" => "line", "text" => "Line", "icon" => "fab fa-line", ), array( "id" => 2, "name" => "google", "text" => "Google", "icon" => "fab fa-google", ), array( "id" => 3, "name" => "facebook", "text" => "Facebook", "icon" => "fab fa-facebook", ), array( "id" => 4, "name" => "twitter", "text" => "Twitter", "icon" => "fab fa-twitter", ), ); ?> <?php foreach($platforms as $platform){ $connected = (in_array(md5(sprintf("%02d",$platform['id'])),$arr_connect))?" checked":""; $status = (in_array(md5(sprintf("%02d",$platform['id'])),$arr_connect))?"ยกเลิก":""; ?> <div class="d-flex py-2 text-<?=$platform['name']?> border-top"> <div class="col offset-lg-1 d-flex flex-fill align-items-center"> <i class="<?=$platform['icon']?> fa-fw fa-2x mr-2"></i> เชื่อมต่อ <?=$platform['text']?> </div> <div class="col col-lg-5 d-flex align-items-center"> <label class="toggle" data-toggle="tooltip" data-placement="top" title="" data-original-title="<?=$status?>เชื่อมต่อ"> <input data-social="<?=$platform['name']?>" class="toggle-checkbox chk-app-<?=$platform['name']?>" type="checkbox" <?=$connected?> > <div class="toggle-switch app-<?=$platform['name']?>"></div> <span class="toggle-label"></span> </label> </div> </div> <?php } ?> <script> // อ้างอิง element ด้วย javascript สามารถประยุกต์ใช้ jquery ได้ถ้าต้องการ var eles = document.querySelectorAll("[data-social]"); eles.forEach( (ele) => { ele.addEventListener("change",(e) => { console.log(e.target.dataset.social); // ชื่อ platform ที่ใช้ หรือเลือก console.log(e.target.checked); // สถานะ platform ที่ใช้หรือเลือก if(e.target.checked==true){ // ถ้าต้องการเชื่อมบัญชี window.location = `socialconnect/${e.target.dataset.social}?action=connect`; }else{ // ถ้ายกเลิกการเชื่อมต่อ if(confirm("ยืนยันการยกเลิกเชื่อมต่อ?")){ window.location = `socialconnect/${e.target.dataset.social}?action=disconnect`; }else{ e.target.checked = true; } } }); }); </script> </div> <div class="bg-light p-3"> <?php $testData = " ID: {$_SESSION['ses_user_id']}<br> Name: {$_SESSION['ses_user_name'] }<br> Email: {$_SESSION['ses_user_email'] }<br> Picture: {$_SESSION['ses_user_picture'] } "; echo $testData; ?> </div> </div> </body> </html>
ในที่นี้ เราสมมติการใช้ตัวแปรของระบบสมาชิกด้วย session ต่างๆ ดังนี้
ID: {$_SESSION['ses_user_id']}<br> Name: {$_SESSION['ses_user_name'] }<br> Email: {$_SESSION['ses_user_email'] }<br> Picture: {$_SESSION['ses_user_picture'] }
ตัวแปร session ชื่อนี้ จะต้องสัมพันธ์กับชื่อที่ใช้และกำหนดในไฟล์ User.php ดังนั้น ให้ตรวจสอบและแก้ไขให้ครบ หากเราใช้เป็นแบบอื่น
ในไฟล์ member เราใช้ checkbox ที่จัดรูปแบบเด้วย css เป็นลักษณะ toggle หากทำการเชื่อมต่อบัญชีใดๆ ก็จะเปลี่ยนสถานะ เมื่อเชื่อมต่อสำเร็จ
และถ้าทำการยกเลิกการเชื่อมต่อ ก็จะแจ้งเตือนการยกเลิกก่อน หากผู้ใช้ยืนยันการยกเลิก ก็ไปทำคำสั่งยกเลิก ที่เราจะเพิ่มเข้าไปในแต่ละ platform
ตามโค้ดด้านล่าง โดยใช้ชื่อว่า disconnect[ชื่อ platform]
จากเดิมในตอนที่ 3 เราคำการคืนค่า user จากไฟล์ User.php ไม่ไว้ในตัวแปร session ในไฟล์ เชื่อมต่อของแต่ละ platform ในกรณีนี้ เราจะย้าย
การกำหนด และใช้งาน session ไปทำในไฟล์ User.php ทั้งหมด และไม่ต้องคืนค่าใดๆ ออกมา
ไฟล์ line.php
<?php session_start(); date_default_timezone_set("Asia/Bangkok"); // โค้ดไฟล์ dbconnect.php ดูได้ที่ http://niik.in/que_2398_5642 require_once('../dbconnect.php'); require_once('../vendor/autoload.php'); use Ninenik\LineOAuth\LineOAuth; require_once('./User.php'); class Socialconnect{ private $_LINE_CLIENT; // $salt สามารถใช้คำสั่ง password_hash("mysslweb",PASSWORD_BCRYPT); สร้างได้ private $_SALT = '$2y$10$cDKiRAzt3zWwiyAu/Nz40Om6yKe1mQZMM4T6yxAlTTI25oIUq9EVm'; // กำหนดค่าที่จะใช้งานในส่วนนี้ private $_CHANNEL_ID = "165xxxxxxx2"; private $_CHANNEL_SECRET = "469xxxxxxxxxxx9ee47d"; private $_CHANNEL_CALLBACK = "https://www.mysslweb.com/socialconnect/line"; private $_DB; // ตัวแปรเชื่อมต่อฐานข้อมูล public function __construct($mysqli){ // รับ parameter การเชื่อมต่อฐานข้อมูล $this->_DB = $mysqli; $this->_LINE_CLIENT = new LineOAuth(); } public function redirect($url){ header("Location:{$url}"); exit; } public function line(){ $this->_LINE_CLIENT->setapp( $this->_CHANNEL_ID, $this->_CHANNEL_SECRET, $this->_CHANNEL_CALLBACK ); } public function connectline(){ $this->line(); $this->_LINE_CLIENT->authorize(); } public function disconnectline(){ $_USER = new User($this->_DB,NULL,1); $_USER->disconnect(); $this->redirect($_SERVER['HTTP_REFERER']); } public function authorizedline($success_url,$error_url){ if(isset($_GET['error'])){ $this->redirect($error_url); }else{ if(isset($_GET['code'])){ $this->line(); $dataToken = $this->_LINE_CLIENT->requestAccessToken($_GET, true); print_r($dataToken); if(array_key_exists('access_token',$dataToken)){ $accessToken = $dataToken['access_token']; } if(array_key_exists('id_token',$dataToken)){ $line_userdata = json_decode($dataToken['user'],true); // ค่า ID , name , picture ที่เราสามารถนำไปใช้ได้ $line_userID = $line_userdata['sub']; $line_userName = $line_userdata['name']; $line_email = $line_userdata['email']; $line_userPicture = $line_userdata['picture']; $hashed_token = crypt($line_userID,$this->_SALT); // เก็บค่าตัวแปร ที่จะส่งไปใช้ในระบบการล็อกอิน และสมัครสมาชิก $userData['id'] = (isset($line_userID))?$line_userID:null; $userData['name'] = (isset($line_userName))?$line_userName:null; $userData['email'] = (isset($line_email))?$line_email:null; $userData['picture'] = (isset($line_userPicture))?$line_userPicture:null; $userData['token'] = (isset($hashed_token))?$hashed_token:null; } if(isset($line_userID) && isset($hashed_token) && isset($accessToken)){ // เรียกใช้งาน User Class กำหนดตัวเลข ชนิดของ ประเภทของ social ที่ใช้งาน // Line , Google , Facebook และ Twitter จะเป็น 1,2,3 และ 4 ตามลำดับ $_USER = new User($this->_DB,$userData,1); $_USER->login(); // เรียกใช้งานคำสั่งสมัคร และล็อกอิน $this->redirect($success_url); }else{ $this->redirect($error_url); } }else{ $this->redirect($error_url); } } } } ?> <?php $social = new Socialconnect($mysqli); // ส่งการเชื่อมกับฐานข้อมูลเข้าไปใช้งาน if(isset($_GET['action']) && $_GET['action']=="connect"){ $social->connectline(); }elseif(isset($_GET['action']) && $_GET['action']=="disconnect"){ $social->disconnectline(); }else{ $social->authorizedline("../member.php","../login.php"); } ?>
ไฟล์ google.php
<?php session_start(); date_default_timezone_set("Asia/Bangkok"); // โค้ดไฟล์ dbconnect.php ดูได้ที่ http://niik.in/que_2398_5642 require_once('../dbconnect.php'); require_once('../vendor/autoload.php'); require_once('./User.php'); class Socialconnect{ private $_GOOGLE_CLIENT; // $salt สามารถใช้คำสั่ง password_hash("mysslweb",PASSWORD_BCRYPT); สร้างได้ private $_SALT = '$2y$10$cDKiRAzt3zWwiyAu/Nz40Om6yKe1mQZMM4T6yxAlTTI25oIUq9EVm'; // กำหนดค่าที่จะใช้งานในส่วนนี้ private $_CLIENT_ID = "108068xxxxxxxxxxxxxhg45i.apps.googleusercontent.com"; private $_CLIENT_SECRET = "ddBxxxxxxxxxxxfhfk"; private $_CLIENT_CALLBACK = "https://www.mysslweb.com/socialconnect/google"; private $_DB; // ตัวแปรเชื่อมต่อฐานข้อมูล public function __construct($mysqli){ // รับ parameter การเชื่อมต่อฐานข้อมูล $this->_DB = $mysqli; $this->_GOOGLE_CLIENT = new Google_Client(); } public function redirect($url){ header("Location:{$url}"); exit; } public function google(){ //Set the OAuth 2.0 Client ID $this->_GOOGLE_CLIENT->setClientId($this->_CLIENT_ID); //Set the OAuth 2.0 Client Secret key $this->_GOOGLE_CLIENT->setClientSecret($this->_CLIENT_SECRET); $this->_GOOGLE_CLIENT->setRedirectUri($this->_CLIENT_CALLBACK); $this->_GOOGLE_CLIENT->addScope('email'); $this->_GOOGLE_CLIENT->addScope('profile'); } public function connectgoogle(){ $this->google(); $this->redirect($this->_GOOGLE_CLIENT->createAuthUrl()); } public function disconnectgoogle(){ $_USER = new User($this->_DB,NULL,2); $_USER->disconnect(); $this->redirect($_SERVER['HTTP_REFERER']); } public function authorizedgoogle($success_url,$error_url){ if(isset($_GET['error'])){ $this->redirect($error_url); }else{ if(isset($_GET['code'])){ $this->google(); $dataToken = $this->_GOOGLE_CLIENT->fetchAccessTokenWithAuthCode($_GET['code']); if(!isset($dataToken['error'])){ $this->_GOOGLE_CLIENT->setAccessToken($dataToken['access_token']); $accessToken = $dataToken['access_token']; //Create Object of Google Service OAuth 2 class $google_service = new Google_Service_Oauth2($this->_GOOGLE_CLIENT); //Get user profile data from google $me = $google_service->userinfo->get(); $google_userdata = array(); $google_userID = $me->getId(); $google_email = $me->getEmail(); $google_name = $me->getName(); $google_picture = $me->getPicture(); $hashed_token = crypt($google_userID,$this->_SALT); // เก็บค่าตัวแปร ที่จะส่งไปใช้ในระบบการล็อกอิน และสมัครสมาชิก $userData['id'] = (isset($google_userID))?$google_userID:null; $userData['name'] = (isset($google_name))?$google_name:null; $userData['email'] = (isset($google_email))?$google_email:null; $userData['picture'] = (isset($google_picture))?$google_picture:null; $userData['token'] = (isset($hashed_token))?$hashed_token:null; } if(isset($google_userID) && isset($hashed_token) && isset($accessToken)){ // เรียกใช้งาน User Class กำหนดตัวเลข ชนิดของ ประเภทของ social ที่ใช้งาน // Line , Google , Facebook และ Twitter จะเป็น 1,2,3 และ 4 ตามลำดับ $_USER = new User($this->_DB,$userData,2); $_USER->login(); // เรียกใช้งานคำสั่งสมัคร และล็อกอิน $this->redirect($success_url); }else{ $this->redirect($error_url); } }else{ $this->redirect($error_url); } } } } ?> <?php $social = new Socialconnect($mysqli); // ส่งการเชื่อมกับฐานข้อมูลเข้าไปใช้งาน if(isset($_GET['action']) && $_GET['action']=="connect"){ $social->connectgoogle(); }elseif(isset($_GET['action']) && $_GET['action']=="disconnect"){ $social->disconnectgoogle(); }else{ $social->authorizedgoogle("../member.php","../login.php"); } ?>
ไฟล์ facebook.php
<?php session_start(); date_default_timezone_set("Asia/Bangkok"); // โค้ดไฟล์ dbconnect.php ดูได้ที่ http://niik.in/que_2398_5642 require_once('../dbconnect.php'); require_once('../vendor/autoload.php'); require_once('./User.php'); class Socialconnect{ private $_FACEBOOK_CLIENT; // $salt สามารถใช้คำสั่ง password_hash("mysslweb",PASSWORD_BCRYPT); สร้างได้ private $_SALT = '$2y$10$cDKiRAzt3zWwiyAu/Nz40Om6yKe1mQZMM4T6yxAlTTI25oIUq9EVm'; // กำหนดค่าที่จะใช้งานในส่วนนี้ private $_APP_ID = "967xxxxxxx469"; private $_APP_SECRET = "15e3xxxxxxxxa9e73"; private $_APP_CALLBACK = "https://www.mysslweb.com/socialconnect/facebook"; private $_DB; // ตัวแปรเชื่อมต่อฐานข้อมูล public function __construct($mysqli){ // รับ parameter การเชื่อมต่อฐานข้อมูล $this->_DB = $mysqli; $this->_FACEBOOK_CLIENT = $this->facebook(); } public function redirect($url){ header("Location:{$url}"); exit; } public function facebook(){ return new \Facebook\Facebook([ 'app_id' => $this->_APP_ID, 'app_secret' => $this->_APP_SECRET, 'default_graph_version' => 'v7.0', //'default_access_token' => '{access-token}', // optional ]); } public function connectfacebook(){ $helper = $this->_FACEBOOK_CLIENT->getRedirectLoginHelper(); $permissions = ['email,public_profile']; // Optional permissions $loginUrl = $helper->getLoginUrl($this->_APP_CALLBACK, $permissions); $this->redirect($loginUrl); } public function disconnectfacebook(){ $_USER = new User($this->_DB,NULL,3); $_USER->disconnect(); $this->redirect($_SERVER['HTTP_REFERER']); } public function authorizedfacebook($success_url,$error_url){ if(isset($_GET['error'])){ $this->redirect($error_url); }else{ if(isset($_GET['code'])){ $helper = $helper = $this->_FACEBOOK_CLIENT->getRedirectLoginHelper(); try { $accessToken = $helper->getAccessToken(); } catch(\Facebook\Exceptions\FacebookResponseException $e) { // When Graph returns an error $this->redirect($error_url); } catch(\Facebook\Exceptions\FacebookSDKException $e) { // When validation fails or other local issues $this->redirect($error_url); } if (isset($accessToken)) { $response = $this->_FACEBOOK_CLIENT->get('/me?fields=id,name,email,picture', $accessToken); $profile_picture = $this->_FACEBOOK_CLIENT->get('/me/picture?type=large', $accessToken); $me = $response->getGraphUser(); $picture = $profile_picture->getHeaders(); $fb_userID = $me->getId(); $fb_name = $me->getName(); $fb_email = $me->getEmail(); $fb_picture = $me->getPicture(); $hashed_token = crypt($fb_userID, $this->_SALT); // เก็บค่าตัวแปร ที่จะส่งไปใช้ในระบบการล็อกอิน และสมัครสมาชิก $userData['id'] = (isset($fb_userID))?$fb_userID:null; $userData['name'] = (isset($fb_name))?$fb_name:null; $userData['email'] = (isset($fb_email))?$fb_email:null; $userData['picture'] = (isset($picture['location']))?$picture['location']:null; $userData['token'] = (isset($hashed_token))?$hashed_token:null; } if(isset($fb_userID) && isset($hashed_token) && isset($accessToken)){ // เรียกใช้งาน User Class กำหนดตัวเลข ชนิดของ ประเภทของ social ที่ใช้งาน // Line , Google , Facebook และ Twitter จะเป็น 1,2,3 และ 4 ตามลำดับ $_USER = new User($this->_DB,$userData,3); $_USER->login(); // เรียกใช้งานคำสั่งสมัคร และล็อกอิน $this->redirect($success_url); }else{ $this->redirect($error_url); } }else{ $this->redirect($error_url); } } } } ?> <?php $social = new Socialconnect($mysqli); // ส่งการเชื่อมกับฐานข้อมูลเข้าไปใช้งาน if(isset($_GET['action']) && $_GET['action']=="connect"){ $social->connectfacebook(); }elseif(isset($_GET['action']) && $_GET['action']=="disconnect"){ $social->disconnectfacebook(); }else{ $social->authorizedfacebook("../member.php","../login.php"); } ?>
ไฟล์ twitter.php
<?php session_start(); date_default_timezone_set("Asia/Bangkok"); // โค้ดไฟล์ dbconnect.php ดูได้ที่ http://niik.in/que_2398_5642 require_once('../dbconnect.php'); require_once('../vendor/autoload.php'); use Abraham\TwitterOAuth\TwitterOAuth; require_once('./User.php'); class Socialconnect{ private $_TWITTER_CLIENT; // $salt สามารถใช้คำสั่ง password_hash("mysslweb",PASSWORD_BCRYPT); สร้างได้ private $_SALT = '$2y$10$cDKiRAzt3zWwiyAu/Nz40Om6yKe1mQZMM4T6yxAlTTI25oIUq9EVm'; // กำหนดค่าที่จะใช้งานในส่วนนี้ private $_API_KEY = "nMSCxxxxxQxxxxxxxxxxb"; private $_API_SECRET = "UUB3OWxxxKeYQKJGicxxxxxxxxikz"; private $_API_CALLBACK = "https://www.mysslweb.com/socialconnect/twitter"; private $_DB; // ตัวแปรเชื่อมต่อฐานข้อมูล public function __construct($mysqli){ // รับ parameter การเชื่อมต่อฐานข้อมูล $this->_DB = $mysqli; $this->_TWITTER_CLIENT = $this->twitter(); } public function redirect($url){ header("Location:{$url}"); exit; } public function twitter($token=null,$token_secret=null){ return new TwitterOAuth( $this->_API_KEY, $this->_API_SECRET, $token, $token_secret); } public function connecttwitter(){ $callback_url = $this->_API_CALLBACK; $request_token = $this->_TWITTER_CLIENT->oauth('oauth/request_token', array('oauth_callback' => $callback_url)); $_SESSION['oauth_token'] = $request_token['oauth_token']; $_SESSION['oauth_token_secret'] = $request_token['oauth_token_secret']; $authUrl = $this->_TWITTER_CLIENT->url('oauth/authorize', array('oauth_token' => $request_token['oauth_token'])); $this->redirect($authUrl); } public function disconnecttwitter(){ $_USER = new User($this->_DB,NULL,4); $_USER->disconnect(); $this->redirect($_SERVER['HTTP_REFERER']); } public function authorizedtwitter($success_url,$error_url){ if(isset($_GET['denied'])){ $this->redirect($error_url); }else{ if(isset($_GET['oauth_verifier'])){ try{ $this->_TWITTER_CLIENT = $this->twitter($_SESSION['oauth_token'],$_SESSION['oauth_token_secret']); $access_token = $this->_TWITTER_CLIENT->oauth("oauth/access_token", ["oauth_verifier" => $_GET['oauth_verifier']]); }catch(\Abraham\TwitterOAuth\TwitterOAuthException $e){ $this->redirect($error_url); } if(isset($access_token['oauth_token']) && isset($access_token['oauth_token_secret']) ){ $this->_TWITTER_CLIENT = $this->twitter($access_token['oauth_token'], $access_token['oauth_token_secret']); $me = $this->_TWITTER_CLIENT->get('account/verify_credentials',['include_email' => true]); $accessToken = $access_token['oauth_token']; $twitter_userdata = array(); $twitter_userdata['picture'] = str_replace("normal","400x400",$me->profile_image_url_https); $twitter_userID = $me->id; $twitter_name = $me->name; $twitter_email = (isset($me->email))?$me->email:null; $twitter_picture =$twitter_userdata['picture']; $hashed_token = crypt($twitter_userID, $this->_SALT); // เก็บค่าตัวแปร ที่จะส่งไปใช้ในระบบการล็อกอิน และสมัครสมาชิก $userData['id'] = (isset($twitter_userID))?$twitter_userID:null; $userData['name'] = (isset($twitter_name))?$twitter_name:null; $userData['email'] = (isset($twitter_email))?$twitter_email:null; $userData['picture'] = (isset($twitter_picture))?$twitter_picture:null; $userData['token'] = (isset($hashed_token))?$hashed_token:null; }else{ $this->redirect($error_url); } if(isset($twitter_userID) && isset($hashed_token) && isset($accessToken)){ // เรียกใช้งาน User Class กำหนดตัวเลข ชนิดของ ประเภทของ social ที่ใช้งาน // Line , Google , Facebook และ Twitter จะเป็น 1,2,3 และ 4 ตามลำดับ $_USER = new User($this->_DB,$userData,4); $_USER->login(); // เรียกใช้งานคำสั่งสมัคร และล็อกอิน $this->redirect($success_url); }else{ $this->redirect($error_url); } }else{ $this->redirect($error_url); } } } } ?> <?php $social = new Socialconnect($mysqli); // ส่งการเชื่อมกับฐานข้อมูลเข้าไปใช้งาน if(isset($_GET['action']) && $_GET['action']=="connect"){ $social->connecttwitter(); }elseif(isset($_GET['action']) && $_GET['action']=="disconnect"){ $social->disconnecttwitter(); }else{ $social->authorizedtwitter("../member.php","../login.php"); } ?>
เป็นอันเสร็จเรียบร้อย ครบทุก platform ให้ดูการทำงาน คำอธิบายใน DEMO ด้านล่าง
ข้อมูลข้างต้น มีการกำหนดชื่อฟิลด์ การใช้ตัวแปร session ด้วยชื่อที่กำหนดขึ้นมา ดังนั้น เราต้องไปปรับใช้ให้เข้ากับตัวแปร session ในระบบ
ของเรา และตรวจสอบการกำหนดค่าต่างๆ ให้สัมพันธ์ หากทำทุกอย่าง ตามเงื่อนไข ก็จะสามารถประยุกต์ใช้งานเพิ่มเติมได้
เนื้อหาเกี่ยวกับการ Integrated Social Login ก็จบไปด้วยทั้งหมด 4 ตอน หวังว่าจะเป็นแนวทางนำไปประยุกต์ใช้งานให้เกิดประโยชน์ต่อไปได้