看一般主流的网站的OAuth登录,基本上都是授权的时候弹出一个小窗,授权成功后小窗自动关闭,然后父页面自动刷新这样的操作。装了TeConnect之后,发现他的逻辑并不是这样的。于是就有接下来的故事了。
刚开始搜了一搜,在Sf上看到了这个:https://segmentfault.com/q/1010000008980773
看完之后,感觉轮询的话...有点浪费性能。想起来泽泽那边的登录逻辑也是这样的。故问之。
经过指引之后,看到了一个dalao的方案。

2020-03-19.png
看完之后可不得了啊。他这个不仅实现了我之前说的功能,而且小窗关闭之后,父页面不但没有整体刷新,而是像一种类似于Ajax的方式把内容给更新了。一通研究后,从他的回调页面上,我发现了些端倪。

<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <title>第三方登录回调</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta charset="utf-8"/>
    <meta name="renderer" content="webkit">
</head>
<body>
    <script type="text/javascript">
    var resp = {"success":false,"code":500,"text":"code不能为空!"};
    window.opener.postMessage(resp, '*');
    setTimeout(function()
    {
        window.close();
    }, 100);
    </script>
</body>
</html>

原来如此,谜题解开。这个方案是用到了window.opener来进行的两个页面之间的参数传递,子页面需要的就是这种弹出来的小窗才可以。
折腾了一会儿之后,我成功的实现了这个办法,得到了和那位dalao所实现的类似的结果。

添加与更改

  • TeConnect by 绛木子 Widget.php 中 Line 122 改为
$this->response->redirect($this->options->index."/oauth_feedback.php?message=successbind");
  • Line 131 改为
$this->response->redirect($this->options->index."/oauth_feedback.php?message=successlogin");
2020年3月21日新增:插件第 90 行和第 76 行也要做出修改,让回调跳出去
第 90 行是为了处理微博互联的时候,如果用户点击微博互联里的取消按钮,微博开放平台仍会进行返回。截取做失败返回处理(仅关闭windows.open打开的窗口,不做任何调用父页面代码的操作)。
第 76 行是为了新用户没有账号的时候进行绑定或者是新注册时候的跳转处理,此处要截取做成功的返回处理,这里也是一个登录成功的入口。
  • 站点根目录 新增 oauth_feedback.php (原谅我比较菜,用JS处理Json弄不明白,没跟原版保持一致)
<?php
    if ($_GET['message'] == "successbind") {
        $response = 'successbind';
    } elseif ($_GET['message'] == "successlogin") {
        $response = 'successlogin';
    }else {
        $response = 'error';
    }
?>
<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <title>第三方登录回调</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1" />
    <meta charset="utf-8"/>
    <meta name="renderer" content="webkit">
</head>
<body>
    <script type="text/javascript">
    var resp = '<?php echo $response; ?>';
    window.opener.postMessage(resp);
    setTimeout(function()
    {
        window.close();
    }, 100);
    </script>
    <a href="/" style="font-size:12px;color:#333">如果长时间停留在此页面,请点这里</a>
</body>
</html>
  • 主题文件 comment.php 恰当位置 添加 (第一行依赖jQ,推荐接下来自己改写用用jQ会非常轻松)
<script>
$("#jq-qq-login").click(function(){
       window.open("写你的互联登录地址,不是回调地址","TencentLogin", "width=450,height=320,menubar=0,scrollbars=1,resizable=1,status=1,titlebar=0,toolbar=0,location=1");
});
function postMessage(backs){
    var back = backs;
    console.log(back);
    if (back == 'successbind') {
        console.log("[OAuth]成功登录并绑定");
        /* 需要执行的东西 比如刷新网页 或者是更改页面上的什么东西 */
    } else if (back == 'successlogin') {
        console.log("[OAuth]成功登录");
        /* 需要执行的东西 比如刷新网页 或者是更改页面上的什么东西 */
    } else {
        console.log("[OAuth]未定义操作");
    }
}
</script>

下图为在我自己站上运行的效果。(手机版的话可能大概率会出现OAuth窗无法关掉的情况,所以增加了手动跳转的a标签,但跳的可不是当前页了,而是首页。有能力的推荐可以改一下)
手机这里无法关掉在我这里的解决方案:php层判断来访是否为手机端,如果是,强制跳转到站点首页(别加什么301头什么的)
1.gif

2020年3月21日小改动:OAuth登录成功之后,通过Ajax替换上用户的脱敏登录信息
2.gif
使用te的独页进行拓展出伪api接口,里面也有扩展性,方便日后搞一些别的东西。

<?php   
/**  
    * API PAGE
    *  
    * @package custom
    */  
?>
<?php if (!defined('__TYPECHO_ROOT_DIR__')) exit;

if(!isset($_GET["model"]) || empty($_GET["model"])){
    header("HTTP/1.1 403 Forbidden");
    exit;
}
    
switch ($_GET["model"]) {
    case 'oauth_user_info':
        header("Content-type: application/json");
        if($this->user->hasLogin()){
            echo '{"username":"'.$this->user->screenName.'","avatar":"'.md5($this->user->mail).'","msg":"hasLogin"}';
        } else {
            echo '{"username":"NULL","avatar":"NULL","msg":"notLogin"}';
        }
        break;
        
    default:
        header("HTTP/1.1 403 Forbidden");
        break;
}
/** Ajax 获取已登录用户基本脱敏信息 */
function ajax_oauth_getinfo () {
    $.ajax({
        type: 'get',
        url: '/api.html?model=oauth_user_info',
        /* API接口情况请根据站点的实际情况和接口的情况进行合理变通 */
        error: function (e) {
            console.log('Ajax GETuserinfo Error');
        },
        success: function (data) {
            console.log("success get from oauth_user_info");
            $.each(data,function(key,val){
                if (key == "username"){
                    $('#jq-oauth-info').html("OAuth已登录:"+ val +" <a target=\"_blank\" href=\"/admin/profile.php\"><span class=\"iconfont icon-shezhi\"></span>");
                                /* 请根据站点的实际情况和评论框的情况进行合理变通,这里仅作参考 */
                }
                if (key == "avatar"){
                    $("#jq-avatar-replace").attr('src','https://gravatar.loli.net/avatar/'+ val + '?s=50&r=G'); 
                                /* 请根据站点的实际情况和评论框的情况进行合理变通,这里仅作参考 */
                }
            });
         
        }
    });
    return false;
}

参考链接

http://blog.haoji.me/java-qq-weibo-login.html
https://blog.csdn.net/u013111454/article/details/80763747
https://blog.csdn.net/happy_jijiawei/article/details/53156590