nodejs实现OAuth2.0授权服务认证


Posted in NodeJs onDecember 27, 2017

OAuth是一种开发授权的网络标准,全拼为open authorization,即开放式授权,最新的协议版本是2.0。

举个栗子:

有一个"云冲印"的网站,可以将用户储存在Google的照片,冲印出来。用户为了使用该服务,必须让"云冲印"读取自己储存在Google上的照片。

传统方法是,用户将自己的Google用户名和密码,告诉"云冲印",后者就可以读取用户的照片了。这样的做法有以下几个严重的缺点。

  1. "云冲印"为了后续的服务,会保存用户的密码,这样很不安全。
  2. Google不得不部署密码登录,而我们知道,单纯的密码登录并不安全。
  3. "云冲印"拥有了获取用户储存在Google所有资料的权力,用户没法限制"云冲印"获得授权的范围和有效期。
  4. 用户只有修改密码,才能收回赋予"云冲印"的权力。但是这样做,会使得其他所有获得用户授权的第三方应用程序全部失效。
  5. 只要有一个第三方应用程序被破解,就会导致用户密码泄漏,以及所有被密码保护的数据泄漏。

所以OAuth就诞生了!

  1. Third-party application:第三方应用程序,本文中又称"客户端"(client),即上一节例子中的"云冲印"。
  2. HTTP service:HTTP服务提供商,本文中简称"服务提供商",即上一节例子中的Google。
  3. Resource Owner:资源所有者,本文中又称"用户"(user)。
  4. User Agent:用户代理,本文中就是指浏览器。
  5. Authorization server:认证服务器,即服务提供商专门用来处理认证的服务器。
  6. Resource server:资源服务器,即服务提供商存放用户生成的资源的服务器。它与认证服务器,可以是同一台服务器,也可以是不同的服务器。

登录层提供令牌(token)的生成,其中token包括:有效期、权限范围。客户端拿到token去访问受限资源。

  1. access_token:请求资源时需要携带的token,即访问token。
  2. refresh_token:刷新token,如果access_token过期,可以使用该token获取一份新的access_token和新的refresh_token。一般refresh_token时效性较长,比如一年,而access_token时效性较短,比如几分钟。
  3. 权限范围:即指定客户端可以获取的资源权限范围。

OAuth授权模式

OAuth有四种授权模式,分别为:

  1. 授权码模式(authorization code)
  2. 简化模式(implicit)
  3. 密码模式(resource owner password credentials)
  4. 客户端模式(client credentials)

1、授权码模式

授权码模式是最为严密的授权模式,整体流程为:浏览器携带必要信息至授权页面,正常登录成功后,返回一个code(授权码),客户端拿到code后在后台获取拿code换取token。

nodejs实现OAuth2.0授权服务认证

nodejs实现OAuth2.0授权服务认证

2、密码模式

密码模式,简单地理解即为使用用户名密码等参数获取access_token,它的步骤如下:

  1. 用户向客户端提供用户名和密码。
  2. 客户端将用户名和密码发给认证服务器,向后者请求令牌。
  3. 认证服务器确认无误后,向客户端提供访问令牌。

nodejs实现OAuth2.0授权服务认证

3、refresh_token的应用

refresh_token被用来获取新的access_token和refresh_token,使用方式简单如下:

nodejs实现OAuth2.0授权服务认证

refresh_token无效:

nodejs实现OAuth2.0授权服务认证

使用nodejs实现OAuth授权服务

技术栈:

  1. nodejs + eggjs
  2. eggjs-oAuth-server插件

具体可以参考:
https://github.com/Azard/egg-oauth2-server
https://cnodejs.org/topic/592b2aedba8670562a40f60b

1、code grant模式测试及单点登录实现

这里我们构建两个站点,一个是7001端口(授权服务),一个是7002端口(客户端),授权模式为code grant。

首先是客户端登录页:

nodejs实现OAuth2.0授权服务认证

单击按钮后直接登录:

nodejs实现OAuth2.0授权服务认证

可以发现,浏览器重定向到授权服务地址,并携带了response_type、client_id、redirect_uri三个参数,登录成功后,浏览器会重定向到redirect_uri指定的地址,即这里的*http://127.0.0.1:7002/auth/redirect*:

如下为授权服务的登录页写法

<form action="/oauth2/authorize?{{query}}" id="form1" name="f" method="post">
  <div class="input_outer">
    <span class="u_user"></span>
    <input name="username" class="text" style="color: #FFFFFF !important" type="text" placeholder="请输入账户">
  </div>
  <div class="input_outer">
    <span class="us_uer"></span>
    <input name="password" class="text" style="color: #FFFFFF !important; position:absolute; z-index:100;"value="" type="password" placeholder="请输入密码">
  </div>
  <div class="mb2"><a class="act-but submit" href="javascript:;" rel="external nofollow" onclick="document.getElementById('form1').submit()" style="color: #FFFFFF">登录</a></div>
</form>

这里的${query}即为客户端登录重定向携带的完整query,然后是/oauth2/authorize路由的写法:

app.all('/oauth2/authorize', app.oAuth2Server.authorize());// 获取授权码

这里调用app.oAuth2Server.authorize()时,插件会自动执行重定向操作,首先是重定向到客户端指定地址,客户端拿到code和state后,再去授权层获取token:

async redirect(){
  // 服务端重定向过来的
  console.log(this.ctx.query)
  const result = await this.ctx.curl('http://127.0.0.1:7001/users/token', {
   dataType: 'json',
   // contentType: 'application/x-www-form-urlencoded', // 默认格式
   method: 'POST',
   timeout: 3000,
   data: {
    grant_type: 'authorization_code',
    code: this.ctx.query.code,
    state: this.ctx.query.state,
    client_id: client_id,
    client_secret: client_secret,
    redirect_uri: redirect_uri,
   }
  });
  this.ctx.body = result.data;
 }

获取到token后正常返回:

nodejs实现OAuth2.0授权服务认证

2、password grant模式测试

首先使用username、password获取access_token:

nodejs实现OAuth2.0授权服务认证

用户名或密码错误时返回:

nodejs实现OAuth2.0授权服务认证

使用token获取授权资源正常返回:

nodejs实现OAuth2.0授权服务认证

以上内容完整源码参考:https://github.com/caiya/eggjs-oAuth2-server

总结

  1. OAuth实际使用时要上https,包括客户端和授权服务端
  2. 授权服务可以使用私钥签名,客户端使用公钥验证,从而保证数据安全性

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

NodeJs 相关文章推荐
在NodeJS中启用ECMAScript 6小结(windos以及Linux)
Jul 15 NodeJs
NodeJS远程代码执行
Aug 28 NodeJs
详解Nodejs的timers模块
Dec 22 NodeJs
nodejs利用http模块实现银行卡所属银行查询和骚扰电话验证示例
Dec 30 NodeJs
nodejs+express实现文件上传下载管理网站
Mar 15 NodeJs
nodejs中模块定义实例详解
Mar 18 NodeJs
nodejs 图解express+supervisor+ejs的用法(推荐)
Sep 08 NodeJs
Nodejs 和 Electron ubuntu下快速安装过程
May 04 NodeJs
NodeJs入门教程之定时器和队列
Mar 08 NodeJs
nodejs中request库使用HTTPS代理的方法
Apr 30 NodeJs
基于NodeJS开发钉钉回调接口实现AES-CBC加解密
Aug 20 NodeJs
ubuntu系统下使用pm2设置nodejs开机自启动的方法
May 12 NodeJs
使用nodejs+express实现简单的文件上传功能
Dec 27 #NodeJs
nodejs超出最大的调用栈错误问题
Dec 27 #NodeJs
nodejs实现简单的gulp打包
Dec 21 #NodeJs
nodejs调取微信收货地址的方法
Dec 20 #NodeJs
基于nodejs实现微信支付功能
Dec 20 #NodeJs
nodeJS微信分享
Dec 20 #NodeJs
NodeJS爬虫实例之糗事百科
Dec 14 #NodeJs
You might like
php数字转汉字代码(算法)
2011/10/08 PHP
php数组函数序列之array_key_exists() - 查找数组键名是否存在
2011/10/29 PHP
PHP中COOKIES使用示例
2015/07/26 PHP
php使用ffmpeg向视频中添加文字字幕的实现方法
2016/05/23 PHP
老生常谈PHP面向对象之标识映射
2017/06/21 PHP
jQuery-Easyui 1.2 实现多层菜单效果的代码
2012/01/13 Javascript
js/jquery去掉空格,回车,换行示例代码
2013/11/05 Javascript
jQuery结合CSS制作动态的下拉菜单
2015/10/27 Javascript
简单的JS时钟实例讲解
2016/01/13 Javascript
BOM系列第三篇之定时器应用(时钟、倒计时、秒表和闹钟)
2016/08/17 Javascript
AngularJs bootstrap详解及示例代码
2016/09/01 Javascript
KnockoutJS 3.X API 第四章之表单submit、enable、disable绑定
2016/10/10 Javascript
angularjs下拉框空白的解决办法
2017/06/20 Javascript
jQuery Pagination分页插件_动力节点Java学院整理
2017/07/17 jQuery
Axios学习笔记之使用方法教程
2017/07/21 Javascript
微信小程序实现富文本图片宽度自适应的方法
2019/01/20 Javascript
详解vue-cli项目开发/生产环境代理实现跨域请求
2019/07/23 Javascript
在react中使用vue的状态管理的方法示例
2020/05/02 Javascript
[34:56]Ti4冒泡赛LGD vs Liquid 1
2014/07/14 DOTA
python socket网络编程之粘包问题详解
2018/04/28 Python
如何用python爬取微博热搜数据并保存
2021/02/20 Python
matplotlib bar()实现多组数据并列柱状图通用简便创建方法
2021/02/24 Python
AmazeUI 图标的示例代码
2020/08/13 HTML / CSS
SNIDEL官网:日本VIVI杂志人气少女第一品牌
2020/03/12 全球购物
不用游标的SQL语句有哪些
2012/09/07 面试题
留学自荐信
2013/10/10 职场文书
酒店管理毕业生自荐信
2013/10/24 职场文书
公司办公室岗位职责
2014/03/19 职场文书
中学生国旗下讲话稿
2014/04/26 职场文书
网络技术专业求职信
2014/05/02 职场文书
雷锋式好少年事迹材料
2014/08/17 职场文书
卫生厅领导班子党的群众路线教育实践活动整改措施
2014/09/20 职场文书
党的群众路线教育实践活动党员个人整改措施
2014/10/27 职场文书
街道党风廉政建设调研报告
2015/01/01 职场文书
《平行四边形的面积》教学反思
2016/02/16 职场文书
go:垃圾回收GC触发条件详解
2021/04/24 Golang