探寻后端技术之广之深
用github账户登录你的网站

过程概述

用github,或者其它任何三方网站的账号来登录你的网站,实现过程可以分解为几个步骤:

  1. 实现网站的自有登录系统
  2. 向github注册网站应用
  3. 用户首次选择github登录时,把用户的github账号绑定到在网站注册的账号。

OAuth授权

主要讲解第2、3步骤的实现,第2步其实就是OAuth授权的流程。

OAuth是什么?


OAUTH协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是OAUTH的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此OAUTH是安全的。
要站在用户的角度来理解这个定义,用户用github账号登录其它三方个人网站,最重要的是要保证第三方网站不能获取到用户的git账号和密码等敏感信息。

OAuth的流程


接入github的OAuth认证

1. 在github注册自己网站的应用

登录github后,Setting > Developer setting > OAuth applications > Register a new application

2. 使用github登录,跳转到 GitHub 用户授权页面,

client_id 必须传其他参数如果有需要就传,例如我这里需要获取用户的邮箱信息,就加了一个 scope=user:email
最终拼成的URL如下:
https://github.com/login/oauth/authorize?client_id=yourclient_id&redirect_uri=your_website_callback_uri&scope=user:email

3. 用户在上步登录之后,会跳转到你设置的redirect_uri

并且会带上一个 code参数,这个参数在后面获取用户token是必须的一个参数。
获取到这个code参数后,在你的业务代码中调用 https://github.com/login/oauth/access_token 这个api,传入client_id client_secret code 这三个参数,可以获取到一个 access_token。

4. 使用access_token获取用户在github的基本信息

调用 https://api.github.com/user?access_token=access_token ,就可以获取到基本的用户信息了。
用户的基本信息有很多, 可以根据第一步的参数scope来设置获取哪些信息。

5. 存储github用户信息,接入自有登录系统

把用户的github信息和用户在你的网站的账号进行绑定后,使用github登录你的网站的功能就实现了。

实例,本站接入自有登录系统的实现思路参考

    public function handleGithubCallback()
    {
        $githubUser = Socialite::driver('github')->user();
        $user = User::where('github_id', $githubUser->id)->first();
        /*用户已经登陆*/
        if (auth()->check()) {
            $currentUser = auth()->user();
            /*当前用户已经绑定了Github账号*/
            if ($currentUser->github_id) {
                /*绑定的Github账号和返回的Github账号一致,直接返回,不用理会*/
                if ($currentUser->github_id == $githubUser->id) {
                    return redirect($this->redirect);
                } /*绑定的Github账号和返回的Github账号不一致,返回错误信息*/
                else {
                    return redirect($this->redirect)->withErrors('Sorry,you have bind a different github account!');
                }
            } /*当前用户没有绑定Github账号,试图绑定*/
            else {
                /*返回的Github账号已经被绑定了,返回错误信息*/
                if ($user) {
                    return redirect($this->redirect)->withErrors('Sorry,this github account has been bind to another account,is that you?');
                } /*返回的Github账号没有被绑定,正常绑定*/
                else {
                    if ($this->bindGithub($currentUser, $this->getDataFromGithubUser($githubUser))) {
                        return redirect($this->redirect)->with('success', '绑定 Github 成功');
                    }
                    return redirect($this->redirect)->withErrors('绑定 Github 失败');
                }
            }
        } /*用户没有登陆*/
        else {
            /*让绑定的用户直接登陆*/
            if ($user) {
                auth()->loginUsingId($user->id);
                return redirect($this->redirect)->with('success', '登录成功');
            } /*一个全新的用户来了!!!尝试注册*/
            else {
                $githubData = $this->getDataFromGithubUser($githubUser);
                session()->put('githubData', $githubData);
                return redirect()->route('github.register');
            }
        }
    }

nginx公众号也会推送好文,主要聊聊后端技术,扫描或者搜索nginx即可添加。 nginx公众号

暂无评论~~