前后端分离项目OAuth第三方登录怎么做(以Github举例)

OAuth是一种授权机制。OAuth过程中,系统会询问数据所有者,是否同意授权第三方应用进入系统获取这些数据,同意,则系统将产生一个短期的进入令牌(token),用来代替密码,供第三方应用使用。

# OAuth流程(假设你的站点是A网站) 1. 用户事件触发(一般点击事件)跳转,到 Github 2. Github 要求用户登录,并询问用户是同意 Github 下放授权码给 A 网站 3. 用户同意,则 Github 重定向到 A 网站,同时携带一个授权码(code,以url拼接形式下放) 4. A 网站使用授权码(code)向 Github 请求令牌(token) 5. Github 返回令牌(token) 6. A 网站使用令牌,向 Github 请求用户数据 7. A 网站取得用户 Github 数据,前端展示登陆,后端存储更新用户数据,并记录登录状态

本示例中,项目前后端分离开发,前端采用大家熟知的vue,后端采用koa2,OAuth逻辑和前后端框架其实无关,只会因为前后端分离在写法和前后端不分离项目上略有不同。下面分别来说说进行OAuth开发前做的准备,以及在前后端项目中如何编写代码。
一、配置Github
链接:https://github.com/settings/a...
前后端分离项目OAuth第三方登录怎么做(以Github举例)
文章图片

Application name:站点名称,这里假设是a
Homepage URL: 主站链接,本地测试,这里是localhost:8001
Authorization callback URL:Github重定向链接,本地测试,这里是localhost:8001/login
确认后,github将生成OAuth所需要的 clientID 和clientSecret
二、前端编写
// 将登录方法封装为插件 oauth.js const getQuery = require('./getQuery') // 个人编写用来获取url query的方法const oauthGithub = { getCode() { const authorize_uri = 'https://github.com/login/oauth/authorize'; const client_id = 'b82f7274e2e996a2cecc'; const redirect_uri = 'http://localhost:8001/login'; location.href = https://www.it610.com/article/`${authorize_uri}?client_id=${client_id}&redirect_uri=${redirect_uri}`; }, async getUser(_this) { const code = getQuery('code'); if (code) { try { const res = await _this.$axios.post(`/api/oauth/github?code=${code}`); if (res.data.errorno) { _this.$root.$emit('toast', { variant: 'danger', text: '登录失败' }); // 自定义toast } else { _this.$store.commit('setUser', res.data.data); // 存储用户数据 _this.$root.$emit('toast', { variant: 'success', text: '登录成功' }); } } catch(err) { _this.$root.$emit('toast', { variant: 'danger', text: '登录失败' }); } } } }module.exports = { oauthGithub }

// 在页面或组件内调用插件方法

二、后端编写
// 将OAuth单独抽离为一个route:oauth.js const router = require('koa-router')() const axios = require('axios') const { SuccessModel, ErrorModel } = require('../model/resModel') const { handleUser } = require('../controller/oauth')router.prefix('/api/oauth')router.post('/github', async function (ctx, next) { const clientID = 'b82f7274e2e996a2cecc' const clientSecret = 'f09aa2=dfhf4ba57b6777307b6200d6d2a'const code = ctx.query.code const tokenRes = await axios({ method: 'post', url: `https://github.com/login/oauth/access_token?client_id=${clientID}&client_secret=${clientSecret}&code=${code}`, headers: { accept: 'application/json' } }) const accessToken = tokenRes.data.access_token if (accessToken) { const resData = https://www.it610.com/article/await axios({ method:'get', url: `https://api.github.com/user`, headers: { accept: 'application/json', Authorization: `token ${accessToken}` } }); const uname = resData.data.login // 用户github账号名 const reqBody = { nickname: resData.data.name, // 用户github昵称 avatar: resData.data.avatar_url, // 用户github头像 self_introduction: resData.data.bio, // 用户github自我介绍 site: 'github', // 标识用户来自github site_id: resData.data.id, // 用户github id create_at: Date.now(), // 用户首次 OAuth 时间 update_at: Date.now() // 用户最近一次 OAuth 时间 } const userData = https://www.it610.com/article/await handleUser(reqBody, uname) // controller方法,用户首次登录则存储用户,二次及以后登录更新数据 if (userData.id) { ctx.session.uid = userData.id //redis存储登录状态 ctx.body = new SuccessModel(userData) } else { ctx.body = new ErrorModel('登录失败') } } })module.exports = router

三、操作演示
  1. A 网站跳转到 Github
前后端分离项目OAuth第三方登录怎么做(以Github举例)
文章图片

  1. 用户确认后,GIthub 重定向到 A 网站,并携带 code
【前后端分离项目OAuth第三方登录怎么做(以Github举例)】前后端分离项目OAuth第三方登录怎么做(以Github举例)
文章图片

  1. 前端拿到URL query 部分的 code,向 Github 请求数据(token及用户数据获取都在都在后端完成)
// 即route: oauth.js 部分逻辑 // 1. 拿到前端传过来的code,向github请求token // 2. 拿到token,向github请求用户数据 // 3. 拿到用户数据,将数据返回给前端

  1. 前端拿到用户数据,进行展示
前后端分离项目OAuth第三方登录怎么做(以Github举例)
文章图片

原文链接:https://www.helloque.site/article/22

    推荐阅读