GitHub OAuth App怎么跳转到用户授权之前的页面?

October 22, 2019 / Deprecated

最近完成了博客的评论系统,第三方登录使用了 GitHub OAuth App。至于教程或者示例,随便谷歌、百度一下都是一大片,或许正是因为查的太多了,以至于所有的教程都在告诉你怎么注册、怎么调用 API、怎么用 XXX 后端获取数据等等等等…

但是他们好像都忽略了一个问题:

—— 在获取 Token 或者用户信息之后,客户端要怎么跳转回用户授权之前的页面?

先声明一下,这篇文章不会教你怎么注册或使用 GitHub OAuth App,如果你还不熟悉它,可以先阅读一下官方文档,如果你不太喜欢英语,可以看看阮一峰的GitHub OAuth 第三方登录示例教程或者其他大佬 / 论坛的教程。

好了,先看一下 GitHub OAuth 的流程:

  1. 浏览器带 client_idredirect_uri 跳转到 GitHub
  2. 用户授权
  3. 如果用户同意授权,GitHub 会返回一个code参数,形式为 https://redirect_uri?code=xxxxxxxxxxxxx
  4. 客户端带code client_idclient_secret发送 POST 请求到 GitHub 获取 token
  5. 客户端使用 token 获取用户信息

如果用 URL 的跳转来表现的话大概就是这样:

blog.com/post/01.html
    ---->
https://github.com/login/oauth/authorize?client_id=xxx&redirect_uri=xxx
    ---->
api.blog.com/?code=xxx        # api.blog.com就是你填在GitHub OAuth App的Callback URL
    ----> POST
https://github.com/login/oauth/access_token
    ---->
???

对!问题来了!

怎么跳转?跳哪里?

作为开发者,我肯定是想跳回blog.com/post/01.html实现无缝体验对吧…

然而就这个问题,不管是 CSDN,还是 Stack Overflow,甚至官方文档,

全都没有!

终于,在死了不知道多少脑细胞后,我想出了如下实现过程:

  1. 假设用户在blog.com/post/01.html这张页面上点击了 GitHub 登录按钮,这个登录按钮不要直接跳转到 GitHub 授权页面,先跳转到你自己设置的 GitHub OAuth App 的 Callback URL,这里假设是api.blog.com,把当前页面的 URL 传给api.blog.com,例如:api.blog.com?url=blog.com/post/01.html

  2. 这样在跳转到api.blog.com的时候,你就知道了点击登录的是哪张页面了,这时候可以把传过来 URL 记录到localStorage或者 Cookie,甚至是后端的 Session,反正不管怎么样,找个地方记录一下就可以了,因为这时候我们还要跳转到github.com,不记录的话就丢失了数据

  3. 用户在github.com完成授权后,还是会跳转到api.blog.com,因为跳转前记录了授权前传来的页面 URL,在你获取到 Token 之后,你可以把 URL 再读取出来:

    // localStorage 这么用
    window.localStorage.getItem('URL');
    
    // Cookie 这么用
    // 这个function w3c抄来的
    function getCookie(cname) {
        var name = cname + "=";
        var ca = document.cookie.split(';');
        for (var i = 0; i < ca.length; i++) {
            var c = ca[i];
            while (c.charAt(0) == ' ') {
                c = c.substring(1);
            }
            if (c.indexOf(name) == 0) {
                return c.substring(name.length, c.length);
            }
        }
        return "";
    }
    getCookie('URL');
    

获取用户信息的请求可以在api.blog.com做,也可以像我一样带着token回到blog.com/post/01.html去做。

因为自己的博客URL 特殊,又是 Hash 又是 URL Param(原本是单页 App,现在已调整为纯静态,但是不影响思路),而且也不想用户在回到页面的时候,URL 后面跟着一个长长的token,我还新加了一个跳转页面 blog.com/r.html,这个页面负责接收token和跳转的页面,将token写入浏览器存储(上面说的localStorage或者 Cookie)之后再进行跳转,在blog.com/post/01.html完成用户信息的调用后删除记录在浏览器存储里面的token

虽然流程跑通了,但是我还是很好奇为什么 GitHub 官方文档里完全找不到这一部分的说明,在搜索引擎上也找不到相关文章…

随便吧,现在看起来,只能这样解决…

← Posts