本篇文章給大家帶來的內容是關於小程式和ThinkPHP5結合實現登入狀態(附代碼),有一定的參考價值,有需要的朋友可以參考一下,希望對你有所協助。
小程式中,一般會涉及三種登入方式:
1. 使用帳號登入
2. 自有的帳號註冊和登入
3. 使用其他第三方平台帳號登入
帳號登入流程:
1. 小程式通過wx.login擷取code,發往後台,後台以此向API換取session_key和openid;
2. 隨機產生字串作為sessionid(key),session_key和openid作為value,存入redis中,為了安全,
存入的時候還應設定一個逾時的時間;
3. 用戶端將返回的sessionid存入storage,調用那些需要登入後才有許可權的訪問的後台服務時,
你可以將儲存在storage中的sessionid取出並攜帶在請求中,後台代碼中擷取到該sessionid後,
從redis中尋找是否有該sessionid存在,存在的話,即確認該session是有效,
繼續後續的代碼執行,否則進行錯誤處理。
本文採用的是自由的帳號註冊和登入,主要思路和流程如下:
1. 進入小程式首先通過wx.login擷取code,通過後台介面發往後台,後台以此向API換取session_key和openid;
2. 判斷資料庫中有無該openid【唯一標識,需和帳號(手機號)綁定】,
-- 如果資料庫中沒有該openid(說明沒有該帳號):
判斷傳過來的手機號是否為空白(登入時會將手機號存到全域變數),如果不為空白,則說明是剛登入過的,然後綁定openid及openid_time(目前時間),
如果手機號也為空白,說明沒登入過,則返回登入失敗資訊,使用戶端跳轉登入頁;
-- 如果資料庫中有該openid(說明資料庫中有相對應的手機號),
判斷openid_time距現在的時間是否大於4小時,如果大於,返回登入失敗資訊,使用戶端跳轉登入頁;
如果小於,則更新openid_time為目前時間,然後返回登入成功資訊及手機號。
3. 登入頁面:判斷資料庫中該手機號是否存在,如果存在,則更新openid_time為目前時間,如果不存在,則添加該手機號使用者。然後跳轉首頁執行wx.login方法,登入成功,保持登陸狀態。
詳細流程:
步驟1:進入小程式首先通過wx.login擷取code,通過後台介面發往後台,後台以此向API換取session_key和openid;
var user_phone = app.globalData.user_phone;wx.login({ success: res => { // 發送 res.code 到後台換取 openId, sessionKey, unionId wx.request({ url: 'http://www.tphoutai.com/wx/index', data: { code: res.code, user_phone: user_phone, }, success: function (result) { var res = result.data; console.log(res); if(res.sendsure == 0){ wx.reLaunch({ url: '../login/login', }) }else if(res.sendsure == 1){ wx.reLaunch({ url: '../index/index', }) } } }) } })
步驟2:判斷資料庫中有無該openid【唯一標識,需和帳號(手機號)綁定】;
// 後台代碼:public function index(Request $request){ $url = "https://api.weixin.qq.com/sns/jscode2session"; // 參數 $params['appid']= '小程式的appid'; $params['secret']= '小程式的AppSecret'; $params['js_code']= $request -> param('code'); $params['grant_type']= 'authorization_code'; $user_phone= $request -> param('user_phone'); // API返回的session_key 和 openid $arr = httpCurl($url, $params, 'POST'); $arr = json_decode($arr,true); // 判斷是否成功 if(isset($arr['errcode']) && !empty($arr['errcode'])){ return json(['code'=>'2','message'=>$arr['errmsg'],"result"=>null]); } $openid = $arr['openid']; $session_key = $arr['session_key']; // 從資料庫中尋找是否有該openid $is_openid = Db::table('user_info')->where('openid',$openid)->find(); // 如果openid存在,更新openid_time,返回登入成功資訊及手機號 if($is_openid){ // openid存在,先判斷openid_time,與現在的時間戳記相比,如果相差大於4個小時,則則返回登入失敗資訊,使用戶端跳轉登入頁,如果相差在四個小時之內,則更新openid_time,然後返回登入成功資訊及手機號; // 根據openid查詢到所在條資料 $data = Db::table('user_info')->where('openid',$openid)->find(); // 計算openid_time與現在時間的差值 $time = time() - $data['openid_time']; $time = $time / 3600; // 如果四個小時沒更新過,則登陸態消失,返回失敗,重新登入 if($time > 4){ return json(['sendsure'=>'0','message'=>'登入失敗',]); }else{ // 根據手機號更新openid時間 $update = Db::table('user_info')->where('openid', $openid)->update(['openid_time' => time()]); // 判斷是否更新成功 if($update){ return json(['sendsure'=>'1','message'=>'登入成功','user_phone' => $data['user_phone']]); }else{ return json(['sendsure'=>'0','message'=>'登入失敗']); } } // openid不存在時 }else{ // dump($user_phone); // 如果openid不存在, 判斷手機號是否為空白 if(isset($user_phone) && !empty($user_phone)){ // 如果不為空白,則說明是登入過的,就從資料庫中找到手機號,然後綁定openid,+時間 // 登入後,手機號不為空白,則根據手機號更新openid和openid_time $update = Db::table('user_info') ->where('user_phone', $user_phone) ->update([ 'openid' => $openid, 'openid_time' => time(), ]); if($update){ return json(['sendsure'=>'1','message'=>'登入成功',]); } }else{ // 如果也為空白,則返回登入失敗資訊,使用戶端跳轉登入頁 return json(['sendsure'=>'0','message'=>'讀取失敗',]); } } }
步驟3:登入頁面:登入成功後,跳轉首頁執行wx.login方法,然後登入成功,保持登陸狀態。
// 前台登入 wx.request({ url: 'http://www.tphoutai.com/wx/login', data: { user_phone: user_phone }, success: function (result) { var res = result.data; if (res.sendsure == 1){ app.globalData.user_phone = that.data.user_phone; wx.reLaunch({ url: '../loading/loading', }) } } })
// 後台登入方法 public function login(Request $request){ // 擷取到前台傳輸的手機號 $user_phone = $request -> param('user_phone'); // 判斷資料庫中該手機號是否存在 $is_user_phone = Db::table('user_info')->where('user_phone',$user_phone)->find(); if(isset($is_user_phone) && !empty($is_user_phone)){ // 登入時,資料庫中存在該手機號,則更新openid_time $update = Db::table('user_info') ->where('user_phone', $user_phone) ->update([ 'openid_time' => time(), ]); if($update){ return json(['sendsure'=>'1','message'=>'登入成功',]); } }else{ $data = [ "user_phone" => $user_phone, "pass" => '12345' ]; // 如果資料庫中不存在該手機號,則進行添加 Db::table('user_info')->insert($data); } return json(['sendsure'=>'1','message'=>'登入成功',]); }
根據API擷取sessionkey 和 openid的方法
function httpCurl($url, $params, $method = 'GET', $header = array(), $multi = false){ date_default_timezone_set('PRC'); $opts = array( CURLOPT_TIMEOUT => 30, CURLOPT_RETURNTRANSFER => 1, CURLOPT_SSL_VERIFYPEER => false, CURLOPT_SSL_VERIFYHOST => false, CURLOPT_HTTPHEADER => $header, CURLOPT_COOKIESESSION => true, CURLOPT_FOLLOWLOCATION => 1, CURLOPT_COOKIE =>session_name().'='.session_id(), ); /* 根據請求類型設定特定參數 */ switch(strtoupper($method)){ case 'GET': // $opts[CURLOPT_URL] = $url . '?' . http_build_query($params); // 連結後拼接參數 & 非? $opts[CURLOPT_URL] = $url . '?' . http_build_query($params); break; case 'POST': //判斷是否傳輸檔案 $params = $multi ? $params : http_build_query($params); $opts[CURLOPT_URL] = $url; $opts[CURLOPT_POST] = 1; $opts[CURLOPT_POSTFIELDS] = $params; break; default: throw new Exception('不支援的請求方式!'); } /* 初始化並執行curl請求 */ $ch = curl_init(); curl_setopt_array($ch, $opts); $data = curl_exec($ch); $error = curl_error($ch); curl_close($ch); if($error) throw new Exception('請求發生錯誤:' . $error); return $data; }
測試結果: