- 所谓第三方登录,实质就是 OAuth 授权;
- 用户想要登录 github 网站,github 网站让用户提供第三方网站的数据,证明自己的身份;
- 获取第三方网站的身份数据,就需要 OAuth 授权;
实现原理
-
A 网站让用户跳转到 GitHub (发起一个认证的请求);
-
将这个认证请求重定向到 github 网站;
-
GitHub 要求用户登录,然后询问
"A 网站要求获得 xx 权限,你是否同意?"
-
用户同意后 GitHub 就会重定向回 A 网站,同时发回一个授权码;
-
A 网站使用授权码,向 GitHub 请求令牌;
-
GitHub 返回令牌;
-
A 网站使用令牌,向 GitHub 请求用户数据;
实现流程
本地创建应用服务
应用登记
-
GitHub 服务器配置
-
setting => developer settings => OAuth Apps => 应用信息填写 => generate a new client secret
-
登记完成之后,获取到生成的 Client ID 和 Client Secret,这就是应用的身份识别码;
github 跳转地址相关
url | 请求方法 | 请求参数 | 说明 |
---|---|---|---|
https://github.com/login/oauth/authorize | GET | client_id: string 应用唯一标识 | 授权码 code 获取地址 |
https://github.com/login/oauth/access_token | POST | client_id: string 用户唯一标识 client_secret 用户申请密钥 code 授权码 |
令牌 获取地址 |
https://api.github.com/user | GET | 请求头添加 { headers: Authorization } 令牌 | 用户信息获取地址 |
代码实现
前端进行登录地址创建
后端进行授权码地址重定向
路由匹配 github 返回地址
获取授权码 code 进行令牌请求
获取令牌请求数据,进行界面渲染
-
index.js
const Koa = require("koa"); const router = require("koa-router")(); const staticFiles = require('koa-static'); const path = require('path'); const views = require('koa-views'); const axios = require('axios'); const qs = require('qs'); const app = new Koa(); let userInfo = {}; app.use(staticFiles(path.resolve(__dirname, "./public"))); app.use(views('views', { map: { html: 'ejs' } })); /* 模板路由处理 */ router.get('/login', async ctx => { await ctx.render('login'); }) router.get('/home', async ctx => { await ctx.render('home', { userInfo }); }) /* 拦截前端的 a 链接跳转 */ router.get('/loginByGithub', async ctx => { /* 跳转到 git 获取授权码的地址 携带了 client_id 参数*/ const path = 'https://github.com/login/oauth/authorize?client_id=3d7f48adf0ebf54b92c8' ctx.redirect(path); }) /* 创建一个授权码的地址路由 */ router.get('/callback/github', async ctx => { const { code } = ctx.query; /* 请求令牌 post params 参数 */ const accessToken = await axios.post('https://github.com/login/oauth/access_token', { client_id: '3d7f48adf0ebf54b92c8', client_secret: '870a993278809793e5aae442331e613e8508f2d1', code }); const { access_token } = qs.parse(accessToken.data); /* 获取用户的信息 */ userInfo = await axios.get('https://api.github.com/user', { /* Bearer 后面记得跟一个空格 */ headers: { Authorization: `Bearer ${access_token}`, } }) userInfo = userInfo.data; ctx.redirect('/home'); }) app.use(router.routes()); app.listen(8888, () => console.log('server is running on port 8888'));
-
login.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>登录界面</title> <link rel="stylesheet" href="/css/user.css"> </head> <body> <div class="form-container"> <h1 class="title">用户登录</h1> <form id="formContainer" class="form-wrapper"> <div class="form-item"> <input id="userName" class="text" type="text" placeholder="请输入登录账号"> </div> <div class="form-item password-container"> <input id="userPassword" type="password" placeholder="请输入登录密码"> </div> <input type="submit" class="signin" value="登录"> </form> <a href="/loginByGithub" class="other-login-methods">使用github账户进行登录</a> <div class="copy-rights"> <p>Copyright © 2015.Company name All rights reserved.<a class="switch-register" href="/register.html">还没有有账号,立即注册</a></p> </div> </div> </body> </html>
OAuth2.0👉 获取令牌四种实现方式
上一篇