PHP + iOS 實(shí)現(xiàn)移動(dòng)端掃碼登錄

前言

最近周末閑著沒事,就想建個(gè)站玩玩.于是就想起了后臺(tái)登陸驗(yàn)證的方式是不是可以玩?zhèn)€新花樣.比如搞個(gè)手機(jī)掃碼登錄驗(yàn)證的方式.說(shuō)干就干,研究一下掃碼登錄的原理(當(dāng)然,如果有什么地方有更好的實(shí)現(xiàn)方法或者錯(cuò)誤的地方歡迎指正).

正文

原理

手機(jī)端掃碼簡(jiǎn)單,就不做闡述.
后臺(tái)使用PHP來(lái)實(shí)現(xiàn).(暫時(shí)只考慮實(shí)現(xiàn),先不考慮其他安全方面的問(wèn)題,功能實(shí)現(xiàn)之后再做考慮).
基本原理:
1.Web前端展示二維碼,二維碼信息中包含有sessionId, 并用輪訓(xùn)的方式來(lái)不斷的從服務(wù)端請(qǐng)求手機(jī)端驗(yàn)證的結(jié)果.
2.手機(jī)端掃碼并獲取sessionId,然后向服務(wù)器提交sessionId以及其他數(shù)據(jù).
3.當(dāng)服務(wù)器接收到手機(jī)端提交的sessionId后,就通過(guò)sessionId來(lái)打通手機(jī)端和Web前端之間的session,并標(biāo)記登錄狀態(tài)為驗(yàn)證通過(guò).
4.Web前端獲取到驗(yàn)證通過(guò)信息后,跳轉(zhuǎn)頁(yè)面.

實(shí)現(xiàn)

iOS 部分實(shí)現(xiàn):
iOS 端的實(shí)現(xiàn)很簡(jiǎn)單, 僅僅是掃碼獲取 sessionId, 然后通過(guò)接口發(fā)送 sessionId 以及其他一些必須數(shù)據(jù).
二維碼掃描不說(shuō)了, 二維碼掃描成功后使用 AFNetworking 向服務(wù)器確認(rèn)登錄信息.
發(fā)送參數(shù)為二維碼信息的 sessionId. 服務(wù)器只要接收到 sessionId 就會(huì)標(biāo)記接收到的 sessionId 所屬回話為已登錄狀態(tài).

/**
 掃描完成回調(diào)
 @param message 二維碼掃描結(jié)果
 */
- (void)qrcodeScanSuccessWithMessage:(NSString *)message {
    if (!message) {
        NSLog(@"message = nil");
        return;
    }
    [[AFHTTPSessionManager manager] POST:@"http://192.168.3.7:8888/qrcodelogin/home/index/deviceLogin" parameters:@{@"sessionId" : message} progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        // 打印服務(wù)器返回信息
        NSLog(@"success = %@", responseObject);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        //  打印報(bào)錯(cuò)信息方便調(diào)試
        NSString* errResponse = [[NSString alloc] initWithData:(NSData *)error.userInfo[AFNetworkingOperationFailingURLResponseDataErrorKey] encoding:NSUTF8StringEncoding];
        NSLog(@"%@", errResponse);
    }];
}

Web 前端實(shí)現(xiàn):
通過(guò)輪詢的方式向服務(wù)器確認(rèn), 移動(dòng)端是否已經(jīng)通過(guò)掃碼驗(yàn)證成功. 獲取到驗(yàn)證成功信息則跳轉(zhuǎn)或者提醒登錄成功(事例中僅僅只是提醒). 否則在延遲2秒后進(jìn)入下一次查詢,直到獲取到登錄成功信息為止.
只上 js 代碼, html 代碼略掉.

// 計(jì)數(shù),方便測(cè)試(可以直觀的查看當(dāng)前調(diào)用的次數(shù))
var count = 0;

// 請(qǐng)求服務(wù)器登錄確認(rèn)(輪詢方法)
function requestCheck(){
    $.post("login",{}, function(data){
           // 服務(wù)器返回非 "no" 字符串就算驗(yàn)證通過(guò), 否則進(jìn)入下一輪查詢
           if (data != "no") {
               $("div.loginBox").html("登錄成功");
           }else {
               // 顯示當(dāng)前輪詢次數(shù)
               $("div.count").html(count++);
               // 每次請(qǐng)求完成后, 延遲 2 秒, 再次進(jìn)行查詢
               setTimeout("requestCheck()", 2000);
           }
    });
}

// button 點(diǎn)擊事件響應(yīng)方法
function cl() {
    // 顯示二維碼
    $("div.loginBox").html("![](qrcode)");
    // 調(diào)用輪詢方法
    requestCheck();
}

PHP 實(shí)現(xiàn):
php 實(shí)現(xiàn)使用了 ThinkPHP 框架
首先是 Web 前端顯示二維碼頁(yè)面的請(qǐng)求方法:

// 登錄頁(yè)
public function index(){
    // 主要用于調(diào)試過(guò)程中, web 和移動(dòng)端 session 是否已經(jīng)打通
    $_SESSION["username"] = "test";
    echo "username = ".$_SESSION["username"];
    $this->display(T('login'));
}

其次是手機(jī)移動(dòng)端掃描二維碼后請(qǐng)求登錄的方法:

// 移動(dòng)端確認(rèn)登錄
public function deviceLogin() {
    $sid = I("post.sessionId");
    $result;
    if ($sid) {
        // 先銷毀當(dāng)前 session
        session('[destroy]');
        // 再獲取 sessionId 對(duì)應(yīng)的 session
        Session_id($sid);
        Session_start();
        // 設(shè)置登錄狀態(tài)(只要 deviceUUID 字段的值存在則視為已經(jīng)登錄)
        $_SESSION['deviceUUID'] = "ABCDESDASDEFSDSDA";
        $result["code"] = 1;
        $result["username"] = $_SESSION["username"];
    }else {
        $result["code"] = 0;
    }
    echo json_encode($result);
}

最后是 Web 前端 Ajax 輪詢請(qǐng)求確認(rèn)登錄狀態(tài)的方法:

// web 前端 ajax 請(qǐng)求確認(rèn)登錄狀態(tài)方法
public function login(){
    if (isset($_SESSION['deviceUUID'])) {
        // 如果 $_SESSION['deviceUUID'] 值存在, 則表明移動(dòng)端確認(rèn)了登錄信息, 表明驗(yàn)證通過(guò)
        // 返回登錄確認(rèn)信息
        echo $_SESSION['deviceUUID'];
    }else {
        // 否則表明移動(dòng)端還未確認(rèn)登錄,
        // 返回還未確認(rèn)登錄信息
        echo "no";
    }
}

最后的最后附上生成二維碼的方法:

public function qrcode(){
    $message = session_id();
    if ($message) {
        // 引入第三方庫(kù)文件
        // 真實(shí)路徑為(Vendor/Phpqrcode/phpqrcode.php)
        Vendor('Phpqrcode.phpqrcode');
        \QRcode::png($message, false, QR_ECLEVEL_L, 4, 2, false, 0xFFFFFF, 0x000000);
    }else {
        echo "error";
    }
}

總結(jié)

1.引入phpqrcode時(shí)候直接把phpqrcode.php文件放在ThinkPHP/Library/Vendor/Phpqrcode路徑下.
2.調(diào)用phpqrcode時(shí)候需要\QRcode::png, 指定命名空間為空(因?yàn)?code>phpqrcode并沒有使用命名空間, 如果直接調(diào)用, 就會(huì)報(bào)錯(cuò)).
3.關(guān)于 短輪詢長(zhǎng)輪詢,在一開始看了網(wǎng)上的介紹之后,感覺使用 長(zhǎng)輪詢 優(yōu)點(diǎn)那么多, 就決定使用 長(zhǎng)輪詢, 結(jié)果嘗試了之后發(fā)現(xiàn)如果在開啟了session的站點(diǎn)使用 長(zhǎng)輪詢 會(huì)造成其他請(qǐng)求的阻塞(之后會(huì)再寫一篇文章討論這個(gè)問(wèn)題,可以先參考這個(gè)帖子).因?yàn)楫?dāng)時(shí)并沒有看到這個(gè)帖子,所以最終暫時(shí)選擇了 短輪詢 來(lái)實(shí)現(xiàn).

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 序 本文主要來(lái)研究一下二維碼登錄的相關(guān)場(chǎng)景和原理。 場(chǎng)景 主要的場(chǎng)景有如下幾個(gè): app掃二維碼登錄pc版系統(tǒng)比如...
    go4it閱讀 849評(píng)論 0 5
  • 最近在做一個(gè)掃碼登錄功能,為此我還在網(wǎng)上搜了一下關(guān)于微信的掃描登錄的實(shí)現(xiàn)方式。當(dāng)這個(gè)功能完成了后,我決定將整個(gè)實(shí)現(xiàn)...
    diandiandidi閱讀 1,002評(píng)論 0 1
  • 其實(shí)自從女兒出生起,我就沒打算送她上什么興趣班。當(dāng)然我并不是抵觸,如果小孩子自愿,我也支持。但我一直在外面,一個(gè)月...
    有魚堂主人閱讀 522評(píng)論 0 0
  • 明天就要講課了,現(xiàn)在才把ppt做完。其實(shí)我之前已經(jīng)做了一份了。但是給別人看看,讓提意見時(shí),發(fā)現(xiàn)等于白做了。感覺自己...
    古月和木涵閱讀 561評(píng)論 0 1
  • 每小時(shí)3個(gè)物種滅絕 英國(guó)生態(tài)學(xué)和水文學(xué)研究中心的杰里米·托馬斯領(lǐng)導(dǎo)的一支科研團(tuán)隊(duì)在最近出版的《科學(xué)》雜志上發(fā)表的英...
    吐槽世界閱讀 587評(píng)論 2 4

友情鏈接更多精彩內(nèi)容