OAuth 及 移动端鉴权调研

OAuth

OAuth是一个解决用户无需向第三方应用提供用户名密码,让第三方应用访问用户私密资源的授权方案。

举例: 用户a,在网站B存有私密信息(年龄、邮箱、头像),而a在访问第三方网站C时,为了让C可以知道a在B网站上的信息,可以通过OAuth授权,让C访问B拿到a的信息。

逻辑步骤

a是下图里的User,B是下图里的Consumer,C是Service Provider

  • B网站支持OAuth协议;
  • C网站在B网站注册,拿到appId和appSecret,并事先编辑验证回调地址;
  • a访问C,并点击获取B网站信息的操作;
  • C网站生成带一个未授权RequestToken的链接并跳转到网站B,要求用户进行授权;
  • 用户登录后点击授权,完成对RequestToken的授权;
  • C网站拿着授权后的RequestToken问B拿AccessToken;
  • 通过AccessToken + 资源接口 访问用户的私密资源;
作者:郭无心
链接:https://www.zhihu.com/question/19851243/answer/75070070
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

此图已联系作者

 +----------+                                           +----------+
 |          |--(A)- Obtaining a Request Token --------->|          |
 |          |                                           |          |
 |          |<-(B)- Request Token ----------------------|          |
 |          |       (Unauthorized)                      |          |
 |          |                                           |          |
 |          |      +--------+                           |          |
 |          |>-(C)-|       -+-(C)- Directing ---------->|          |
 |          |      |       -+-(D)- User authenticates ->|          |
 |          |      |        |      +----------+         | Service  |
 | Consumer |      | User-  |      |          |         | Provider |
 |          |      | Agent -+-(D)->|   User   |         |          |
 |          |      |        |      |          |         |          |
 |          |      |        |      +----------+         |          |
 |          |<-(E)-|       -+-(E)- Request Token ------<|          |
 |          |      +--------+      (Authorized)         |          |
 |          |                                           |          |
 |          |--(F)- Obtaining a Access Token ---------->|          |
 |          |                                           |          |
 |          |<-(G)- Access Token -----------------------|          |
 +----------+                                           +----------+

版本信息

OAuth目前有三个版本

  • OAuth1.0 解决用户资源授权问题,以前的OpenId只解决了who的问题,没办法对资源进行区分隔离
  • OAuth1.0a 为了解决OAuth1.0存在的安全漏洞,做了个升级补丁
  • OAuth2.0 由于OAuth1.0的签名认证逻辑过于复杂、对多终端不友好,所以做了2.0的协议,不兼容OAuth1.0。OAuth2.0 支持多种授权方式(方便不同终端对接)。

服务端对接

以Nodejs为例

使用社区方案passport,passport定义了一套权限认证接口。主流的第三方OAuth登录有对应的passport接口实现,如:facebook、twitter、google等。github搜索 passport ${platform}就能找到响应的实现。

具体步骤:

  1. 到对应平台的开发者中心,申请 appId, appSecret,并配置callback回调地址(上图中E步在Consumer的地址);
  2. 服务端(Nodejs): 根据passport strategy对应文档,配置appId、appSecret;
  3. 网页端: 加*问对应strategy的链接增加授权入口;
  4. 移动端: 根据平台提示,下载对应移动端SDK;

注意,找到的strategy有的是走 OAuth1.0a 有的是走 OAuth2.0 的,比如twitter是OAuth1.0a,如果后端需要拿AccessToken则要自己实现(OAuth2.0回调时直接返回AccessToken),使用的时候需要看清楚。

移动端鉴权方案

上面介绍完OAuth token完成第三方鉴权,并获取资源。

我们自己的服务对于移动端鉴权也可以完成OAuth支持,比如Nodejs可以用oauth2orize

使用OAuth支持移动端存在的问题

颁发出去的accessToken需要存储并控制过期,redis会比较合适。

其他方案?—— 自己实现cookie session机制

而如果已经使用了redis,则实现类似cookie-session的机制逻辑上更简单,而且接口鉴权跟web端基本保持一致。

请求时带着token,在后端通过加盐hash等手段生成sessionId,恢复session并进行鉴权,这样可以做到前端和app端统一登录,并且走同一套session存储。

这么做的工作量是重写session模块,在浏览器端解析token并完成session设置。同时redis依然是系统依赖。

有更简洁的方法吗? —— jwt

https://jwt.io

当然有,对于鉴权我们的需求是两个: 鉴权、恢复信息。

jwt可以同时完成,token鉴权、payload存储信息的功能。

操作步骤如下:

  1. 用户通过鉴权接口 (用户名密码登录/第三方登录后的AccessToken鉴权),服务端返回生成的 jwt,jwt中包含了用户的非敏感信息(session);
  2. 移动端拿到jwt后,存储在本地,并按照约定的时间通过AccessToken等方式到后端刷新 jwt;(具体过期时间和过期策略可以服务端跟客户端商量)
  3. 新的请求带着jwt时,服务端只要解析jwt,并取出payload做为session供后面的业务逻辑使用就行了;

缺点:

  1. 请求协议如果不是ssl,则jwt的payload是暴露在网路中的,所以里面不能存储敏感信息;
  2. jwt相对一般的token体量大,网络开销受payload体积影响,因此session不宜太大;

实现cookie session机制用redis存储的方式可以作为升级方案。

有更好的方案欢迎讨论

reply to start a discussion

References

上一篇:设计模式——21访问者模式(Visitor)


下一篇:[雪峰磁针石博客]python库介绍-collections:高性能容器数据类型