React + Node 单页应用「二」OAuth 2.0 授权认证 & GitHub 授权实践
关于项目
记录最近做的一个 demo,前端使用 React
,用 React Router
实现前端路由,Koa 2
搭建 API Server, 最后通过 Nginx
做请求转发。
文章列表
第一篇:React + Node 单页应用「一」前端搭建
React + Node 单页应用「二」OAuth 2.0 授权认证 & GitHub 授权实践
这是第二篇,介绍下 OAuth 2.0
授权机制,以及 Github App 授权过程,通过获取授权使用 Github API。
OAuth 2.0
背景
传统的 CS(Client-Server) 授权模式下,请求访问受保护资源(用户信息)时,客户端需要向服务器提供资源所属用户的证书,为了让第三方拿到资源,用户就得将证书共享给第三方应用。这种方式会导致以下几个问题:
- 第三方应用为了长久使用,需要存储用户凭证,特别是明文密码。
- 服务器需要支持密码验证,虽然密码存在固有的安全缺陷。
- 第三方应用获得了资源的过度访问权限,导致用户在授权期间无法限制第三方应用的访问权限。
- 用户不能单独撤销某一个第三方应用的访问权限,必须修改密码来撤销所有授权应用的权限。
- 任何第三方应用的漏洞都可能会威胁到用户的密码,以及对应密码权限下的用户数据。
为了解决这个问题,OAuth 协议引入了授权层,并将客户端与服务端的角色区分开,在 OAuth 协议中,客户端请求的 Access_token
,被托管在资源服务器,但受用户控制,并且与用户凭证完全不同。
举个例子,现在有一家档案馆,档案馆中有很多资料,这些资料有些涉及到机密,有些只是常规资料,
研究员小李需要进入档案馆查找常规资料,于是就跑去找罗馆长批条子
“馆长馆长,我要看一些常规资料,请给我批个条子吧”
罗馆长了解了小李要看的是常规资料,很爽快地批了
“没问题,给,这是同意的条子”
于是小李拿到条子后,径直去找了档案馆门卫大壮
“大壮,你看这是馆长给我批的查看常规资料的条子”,
大壮确认没问题后
“嗯,既然馆长同意了,来,这是常规文件的钥匙”,
于是小李就拿着钥匙进入馆内开始找资料,馆内每道房门都有一把锁,如果房间里存放的是常规资料,小李只需要出示钥匙就可以进入,但存放涉密资料的房间,小李的钥匙打不开,必须找馆长批一份查看涉密资料的条子,再拿着条子去大壮那儿换一把新的钥匙。
角色
资源所有者
可以授权获取受保护资源的实体,如果这个所有者是人,即常规意义的用户,即档案馆的馆长。资源服务器
资源服务器用于存储资源,接收请求,并将资源返回给携带合法Access_token
的请求,在我们的例子中,档案馆就充当着资源服务器的角色。客户端
获取授权后,代表用户请求资源的第三方应用,也就是故事中的研究员小李。授权服务器
授权服务器在成功认证资源拥有者并获取到授权后,发放Access_token
给客户端,故事中大壮的主要工作内容就是发放访问钥匙。
授权流程
/**
* 协议流程
* 引自 RFC6749
*/
+--------+ +---------------+
| |--(A)- Authorization Request ->| Resource |
| | | Owner |
| |<-(B)-- Authorization Grant ---| |
| | +---------------+
| |
| | +---------------+
| |--(C)-- Authorization Grant -->| Authorization |
| Client | | Server |
| |<-(D)----- Access Token -------| |
| | +---------------+
| |
| | +---------------+
| |--(E)----- Access Token ------>| Resource |
| | | Server |
| |<-(F)--- Protected Resource ---| |
+--------+ +---------------+
上面这张图是引自 RFC6749 的 OAuth 2.0 授权流程,概括如下
- 第三方应用向用户请求授权,用户同意,第三方拿到授权许可
- 第三方拿着用户的授权许可,请求授权服务器要访问数据的
Access_token
- 带着
Access_token
,第三方应用就可以访问资源服务器中的资源了
Github APP 授权
Github 有一套非常完备的 API,在没有获得授权时,仅有部分功能可用,例如获取用户信息、仓库信息等,并且调用次数被限制在了一小时仅允许60次
授权后,每小时调用次数放开到每小时 5000 次,并且申请授权时,可以选择申请的权限范围,例如申请 star 项目、follow 用户的权限(我们这次用到的)等等,我们通过申请完整的权限,甚至可以写一个 Github 第三方应用。
注册并配置 APP
要获取授权,首先需要在 Github 注册一个应用,注册这个应用之前,需要准备好两个东西
- 用作应用主页访问的 URL,例如
github.lijundong.com
(如果是 IP 记得加协议头) - 用作接受授权回调的的 URL,例如
github.lijundong.com/github/getauth
可依照以下路径创建一个授权 APP,
Github > setting > Developer settings > OAuth Apps > New OAuth App
进入注册界面,需要填写应用名、应用主页地址、应用简介、以及回调 URL,创建完成会跳转到 APP 管理页面,在管理页面可以更新应用信息以及上传应用 Logo,并且你将看到你的应用的 Client ID
、Client Secret
,接下来获取权限需要用到这两个东西。
授权流程
GitHub 官方的授权流程:
第一步:页面跳转到 GitHub 的授权页
在项目中,我选择了用 <a>
标签链接的方式跳转。
GET https://github.com/login/oauth/authorize?client_id=xxx&scope=xxx
/**
* client_id:注册应用的 client_id 必填
* scope:申请的权限范围 选填,默认用户权限为空
*/
第二步:回调接口收到 GitHub 的回调请求,获得 code
我们在注册应用时,设置了授权回调 URL,上一步中,Github 授权页成功获得用户授权后,会带上 code 请求我们设置的回调 URL,在这一步中,我们的 Server 就拿到了用户的授权 code。
第三步:通过 code 获取 Access_token
最后一步通过已有 code,加上应用的 client_id
和 client_secret
,我们向 Github 申请 Access_token
。
/**
* code:第二步获取到的 code 必填
* client_secret:注册应用 client_secret 必填
* client_id:注册应用的 client_id 必填
*/
const rp = require('request-promise')
let option = {
uri: 'https://github.com/login/oauth/access_token?client_id=' + clientId + '&client_secret=' + clientSecret + '&code=' + code,
json: true
}
let tokenResp = await rp(option);
第四步:将获得的 Access_token
写入页面的 cookie 中。
ctx.cookies.set('access_token', tokenResp.access_token, {
'httpOnly': false
})
获取用户数据
因为第三方应用请求 GitHub API 涉及到跨域,第一篇文章已经提到了Github API 只支持 XHR 跨域请求,一些同学如果用 Fetch 跨域请求 API 会导致请求 request type
变成 option
,所以项目中改用 axios
进行网络请求。
这里以获取登陆用户基本信息为例,
import Axios from 'axios'
import Cookie from 'js-cookie'
const access_token = Cookie.get('access_token');
getLoginInfo() {
let that = this;
let url = API.GITHUB.GET_LOGIN_INFO;
Axios.get(url, {
params: {
access_token: access_token
}
}).then(function(res) {
that.setState({
loginInfo: res.data,
});
}).catch(function (error) {
console.error(error);
})
}
参考:
React + Node 单页应用「二」OAuth 2.0 授权认证 & GitHub 授权实践的更多相关文章
- React + Node 单页应用「一」前端搭建
项目地址 预览地址 原文地址 记录最近做的一个 demo,前端使用 React,用 React Router 实现前端路由,Koa 2 搭建 API Server, 最后通过 Nginx 做请求转发. ...
- React构建单页应用方法与实例
React作为目前最流行的前端框架之一,其受欢迎程度不容小觑,从这门框架上我们可以学到许多其他前端框架所缺失的东西,也是其创新性所在的地方,比如虚拟DOM.JSX等.那么接下来我们就来学习一下这门框架 ...
- [译]用AngularJS构建大型ASP.NET单页应用(二)
原文地址:http://www.codeproject.com/Articles/808213/Developing-a-Large-Scale-Application-with-a-Single 客 ...
- JavaScript 引擎「V8」发布 8.0 版本,内存占用量大幅下降
上周,JavaScript 引擎「V8」的开发团队在该项目官方网站上正式宣布推出最新的 8.0 版本.这次更新的重点主要集中在错误修复及性能改善上,正式的版本将在数周后随着谷歌 Chrome 80 稳 ...
- 跟我一起学习vue2(使用命令行搭建单页应用)[二]
第一步:运行git命令,全局安装 vue-cli $ cnpm install --global vue-cli 第二步: 创建一个基于 webpack 模板的新项目 $ vue init webpa ...
- 「Vue」vue-cli 3.0集成sass/scss到vue项目
vue-cli 3提供了两种方式集成sass/scss: 创建项目是选择预处理器sass手动安装sass-loader创建项目选择预处理器sass$ vue create vuedemo? Pleas ...
- 「Django」rest_framework学习系列-版本认证
1.自己写: class UserView(APIView): versioning_class = ParamVersion def get(self,request,*args,**kwargs) ...
- 「Django」rest_framework学习系列-权限认证
权限认证:1.项目下utils文件写permissions.py文件 from rest_framework.permissions import BasePermission class SVIPP ...
- 「Django」rest_framework学习系列-用户认证
用户认证:1.项目下utils文件写auth.py文件 from rest_framework import exceptions from api import models from rest_f ...
随机推荐
- 五年.net程序员转型Java之路
大学毕业后笔者进入一家外企,做企业CRM系统开发,那时候开发效率最高的高级程序语言,毫无疑问是C#.恰逢公司也在扩张,招聘了不少.net程序员,笔者作为应届生,也乐呵呵的加入到.net程序员行列中. ...
- 【微信小程序】调用wx.request接口需要注意的问题
写在前面 之前写了一篇<微信小程序实现各种特效实例>,上次的小程序的项目我负责大部分前端后台接口的对接,然后学长帮我改了一些问题.总的来说,收获了不少吧! 现在项目已经完成,还是要陆陆续续 ...
- 虚拟机中ubuntu-16.04 Linux系统下配置mysql数据库,并在windows下使用navicat远程连接
Linux系统下mysql数据库安装配置步骤: 1.在服务器上安装mysql:sudo apt-get install mysql-server sudo apt-get install mysql- ...
- hdu 4057--Rescue the Rabbit(AC自动机+状压DP)
题目链接 Problem Description Dr. X is a biologist, who likes rabbits very much and can do everything for ...
- [Python]Codecombat攻略之地牢Kithgard(1-22关)
首页:https://cn.codecombat.com/play语言:Python 第一界面:地牢 Kithgard(22关) 时间:1-3小时 内容:语法.方法.参数.字符串.循环.变量等 网页: ...
- 1、Http概述
1.1 Web客户端和服务器 HTTP 客户端和 HTTP 服务器共同构成了万维网的基本组件,客户端向服务器发送 HTTP 请求, 服务器会在 HTTP 响应中回送所请求的数据. 示意图: 1.2 媒 ...
- 多个code.csdn.net账号切换
code.csdn.net是国内开源库 使用git需要在项目添加密钥 而如果有多个账户,一个是私人,一个是公司,那么这时怎么做? 密钥存在~/.ssh默认是id_rsa 那么一个比较笨的办法是做一个k ...
- win10 & Ubuntu16 双系统安装
忽然心血来潮吧,本机在已经安装了win10的背景下,想要再加一个linux系统学习学习,几经波折,终于成功. 博主笔记本里有两块固态,一个250G的装了win10,装的时间不久,镜像是在msdn上下载 ...
- 【转】花开正当时,十四款120/128GB SSD横向评测
原文地址:http://www.expreview.com/19604-all.html SSD横评是最具消费指导意义的评测文章,也是各类热门SSD固态硬盘的决斗疆场.SSD评测在行业内已经有不少网站 ...
- (转)JVM性能调优之生成堆的dump文件
转自:http://blog.csdn.net/lifuxiangcaohui/article/details/37992725 最近因项目存在内存泄漏,故进行大规模的JVM性能调优 , 现把经验做一 ...