旅行者一号 發表於 2020-5-25 10:29:00

GitHub OAuth 第三方登录示例教程(转)

<p>  http://www.ruanyifeng.com/blog/2019/04/github-oauth.html</p>
<p>  </p>
<p>这组 OAuth 系列教程,第一篇介绍了基本概念,第二篇介绍了获取令牌的四种方式,今天演示一个实例,如何通过 OAuth 获取 API 数据。</p>
<p>很多网站登录时,允许使用第三方网站的身份,这称为"第三方登录"。</p>
<p><img src="https://img2020.cnblogs.com/blog/545911/202005/545911-20200525102458543-211837289.png"></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;下面就以 GitHub 为例,写一个最简单的应用,演示第三方登录。</p>
<h2>一、第三方登录的原理</h2>
<p>  </p>
<p>所谓第三方登录,实质就是 OAuth 授权。用户想要登录 A 网站,A 网站让用户提供第三方网站的数据,证明自己的身份。获取第三方网站的身份数据,就需要 OAuth 授权。</p>
<p>举例来说,A 网站允许 GitHub 登录,背后就是下面的流程。</p>
<blockquote><ol start="1">
<li>A 网站让用户跳转到 GitHub。</li>
<li>GitHub 要求用户登录,然后询问"A 网站要求获得 xx 权限,你是否同意?"</li>
<li>用户同意,GitHub 就会重定向回 A 网站,同时发回一个授权码。</li>
<li>A 网站使用授权码,向 GitHub 请求令牌。</li>
<li>GitHub 返回令牌.</li>
<li>A 网站使用令牌,向 GitHub 请求用户数据。</li>
</ol></blockquote>
<p>下面就是这个流程的代码实现。</p>
<h2>二、应用登记</h2>
<p>一个应用要求 OAuth 授权,必须先到对方网站登记,让对方知道是谁在请求。</p>
<p>所以,你要先去 GitHub 登记一下。当然,我已经登记过了,你使用我的登记信息也可以,但为了完整走一遍流程,还是建议大家自己登记。这是免费的。</p>
<p>访问这个网址,填写登记表。</p>
<p><img src="https://img2020.cnblogs.com/blog/545911/202005/545911-20200525102603869-1850732020.png"></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>应用的名称随便填,主页 URL 填写<code>http://localhost:8080</code>,跳转网址填写&nbsp;<code>http://localhost:8080/oauth/redirect</code>。</p>
<p>提交表单以后,GitHub 应该会返回客户端 ID(client ID)和客户端密钥(client secret),这就是应用的身份识别码。</p>
<h2>三、示例仓库</h2>
<p>我写了一个代码仓库,请将它克隆到本地。</p>
<blockquote>
<pre class=" language-bash"><code class=" language-bash">
$ git clone git@github<span class="token punctuation">.com<span class="token punctuation">:ruanyf<span class="token operator">/node<span class="token operator">-oauth<span class="token operator">-demo<span class="token punctuation">.git
$ cd node<span class="token operator">-oauth<span class="token operator">-demo
</span></span></span></span></span></span></span></span></code></pre>
</blockquote>
<p>两个配置项要改一下,写入上一步的身份识别码。</p>
<blockquote>
<ul>
<li><code>index.js</code>:改掉变量<code>clientID</code>&nbsp;and&nbsp;<code>clientSecret</code></li>
<li><code>public/index.html</code>:改掉变量<code>client_id</code></li>
</ul>
</blockquote>
<p>然后,安装依赖。</p>
<blockquote>
<pre class=" language-bash"><code class=" language-bash">
$ npm install
</code></pre>
</blockquote>
<p>启动服务。</p>
<blockquote>
<pre class=" language-bash"><code class=" language-bash">
$ node index<span class="token punctuation">.js
</span></code></pre>
</blockquote>
<p>浏览器访问<code>http://localhost:8080</code>,就可以看到这个示例了。</p>
<h2>四、浏览器跳转 GitHub</h2>
<p>示例的首页很简单,就是一个链接,让用户跳转到 GitHub。</p>
<p><img src="https://img2020.cnblogs.com/blog/545911/202005/545911-20200525102702577-80240375.png"></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>跳转的 URL 如下。</p>
<blockquote>
<pre class=" language-markup"><code class=" language-markup">
https://github.com/login/oauth/authorize?
client_id=7e015d8ce32370079895&amp;
redirect_uri=http://localhost:8080/oauth/redirect
</code></pre>
</blockquote>
<p>这个 URL 指向 GitHub 的 OAuth 授权网址,带有两个参数:<code>client_id</code>告诉 GitHub 谁在请求,<code>redirect_uri</code>是稍后跳转回来的网址。</p>
<p>用户点击到了 GitHub,GitHub 会要求用户登录,确保是本人在操作。</p>
<h2>五、授权码</h2>
<p>登录后,GitHub 询问用户,该应用正在请求数据,你是否同意授权。</p>
<p><img src="https://img2020.cnblogs.com/blog/545911/202005/545911-20200525102729255-2099634329.png"></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>用户同意授权, GitHub 就会跳转到<code>redirect_uri</code>指定的跳转网址,并且带上授权码,跳转回来的 URL 就是下面的样子。</p>
<blockquote>
<pre class=" language-markup"><code class=" language-markup">
http://localhost:8080/oauth/redirect?
code=859310e7cecc9196f4af
</code></pre>
</blockquote>
<p>后端收到这个请求以后,就拿到了授权码(<code>code</code>参数)。</p>
<h2>六、后端实现</h2>
<p>示例的后端采用 Koa 框架编写,具体语法请看教程。</p>
<p>这里的关键是针对<code>/oauth/redirect</code>的请求,编写一个路由,完成 OAuth 认证。</p>
<blockquote>
<pre class=" language-javascript"><code class=" language-javascript">
const oauth <span class="token operator">= async ctx <span class="token operator">=<span class="token operator">&gt; <span class="token punctuation">{
<span class="token comment"> // ...
<span class="token punctuation">}<span class="token punctuation">;

app<span class="token punctuation">.<span class="token function">use<span class="token punctuation">(route<span class="token punctuation">.<span class="token function">get<span class="token punctuation">(<span class="token string">'/oauth/redirect'<span class="token punctuation">, oauth<span class="token punctuation">)<span class="token punctuation">)<span class="token punctuation">;
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</blockquote>
<p>上面代码中,<code>oauth</code>函数就是路由的处理函数。下面的代码都写在这个函数里面。</p>
<p>路由函数的第一件事,是从 URL 取出授权码。</p>
<blockquote>
<pre class=" language-javascript"><code class=" language-javascript">
const requestToken <span class="token operator">= ctx<span class="token punctuation">.request<span class="token punctuation">.query<span class="token punctuation">.code<span class="token punctuation">;</span></span></span></span></span></code></pre>
</blockquote>
<h2>七、令牌</h2>
<p>后端使用这个授权码,向 GitHub 请求令牌。</p>
<blockquote>
<pre class=" language-javascript"><code class=" language-javascript">
const tokenResponse <span class="token operator">= await <span class="token function">axios<span class="token punctuation">(<span class="token punctuation">{
method<span class="token punctuation">: <span class="token string">'post'<span class="token punctuation">,
url<span class="token punctuation">: <span class="token string">'https://github.com/login/oauth/access_token?' <span class="token operator">+
    `client_id<span class="token operator">=$<span class="token punctuation">{clientID<span class="token punctuation">}<span class="token operator">&amp;` <span class="token operator">+
    `client_secret<span class="token operator">=$<span class="token punctuation">{clientSecret<span class="token punctuation">}<span class="token operator">&amp;` <span class="token operator">+
    `code<span class="token operator">=$<span class="token punctuation">{requestToken<span class="token punctuation">}`<span class="token punctuation">,
headers<span class="token punctuation">: <span class="token punctuation">{
    accept<span class="token punctuation">: <span class="token string">'application/json'
<span class="token punctuation">}
<span class="token punctuation">}<span class="token punctuation">)<span class="token punctuation">;
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</blockquote>
<p>上面代码中,GitHub 的令牌接口<code>https://github.com/login/oauth/access_token</code>需要提供三个参数。</p>
<blockquote>
<ul>
<li><code>client_id</code>:客户端的 ID</li>
<li><code>client_secret</code>:客户端的密钥</li>
<li><code>code</code>:授权码</li>
</ul>
</blockquote>
<p>作为回应,GitHub 会返回一段 JSON 数据,里面包含了令牌<code>accessToken</code>。</p>
<blockquote>
<pre class=" language-javascript"><code class=" language-javascript">
const accessToken <span class="token operator">= tokenResponse<span class="token punctuation">.data<span class="token punctuation">.access_token<span class="token punctuation">;
</span></span></span></span></code></pre>
</blockquote>
<h2>八、API 数据</h2>
<p>有了令牌以后,就可以向 API 请求数据了。</p>
<blockquote>
<pre class=" language-javascript"><code class=" language-javascript">
const result <span class="token operator">= await <span class="token function">axios<span class="token punctuation">(<span class="token punctuation">{
method<span class="token punctuation">: <span class="token string">'get'<span class="token punctuation">,
url<span class="token punctuation">: `https<span class="token punctuation">:<span class="token operator">/<span class="token operator">/api<span class="token punctuation">.github<span class="token punctuation">.com<span class="token operator">/user`<span class="token punctuation">,
headers<span class="token punctuation">: <span class="token punctuation">{
    accept<span class="token punctuation">: <span class="token string">'application/json'<span class="token punctuation">,
    Authorization<span class="token punctuation">: `token $<span class="token punctuation">{accessToken<span class="token punctuation">}`
<span class="token punctuation">}
<span class="token punctuation">}<span class="token punctuation">)<span class="token punctuation">;
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</blockquote>
<p>上面代码中,GitHub API 的地址是<code>https://api.github.com/user</code>,请求的时候必须在 HTTP 头信息里面带上令牌<code>Authorization: token 361507da</code>。</p>
<p>然后,就可以拿到用户数据,得到用户的身份。</p>
<blockquote>
<pre class=" language-javascript"><code class=" language-javascript">
const name <span class="token operator">= result<span class="token punctuation">.data<span class="token punctuation">.name<span class="token punctuation">;
ctx<span class="token punctuation">.response<span class="token punctuation">.<span class="token function">redirect<span class="token punctuation">(`<span class="token operator">/welcome<span class="token punctuation">.html<span class="token operator">?name<span class="token operator">=$<span class="token punctuation">{name<span class="token punctuation">}`<span class="token punctuation">)<span class="token punctuation">;</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</blockquote>
<p>&nbsp;</p><br><br>
来源:https://www.cnblogs.com/lzphu/p/12955429.html
頁: [1]
查看完整版本: GitHub OAuth 第三方登录示例教程(转)