也许,这样理解OAuth原理更容易!

更新日期: 2019-11-15阅读: 1.9k标签: 原理

那一年,我所在公司的用户量达到了公司成立以来的新高峰,经过多个程序员日日夜夜加班,每个业务系统达到了几乎四个 9 的稳定性,同时业务在业界也有了一定的知名度。

PS:以下业务场景只针对于 Web 系统,而且 Web 页面有后台服务程序的场景。

那一天突然有一个合作商登门拜访,提出合作共赢的意向。业务的场景就是我们的系统用户能够在他们系统登录,并能够获取用户一定的信息以便进行一些业务操作。

他们希望我们能够把已存在的用户数据 Copy 一份导入他们的系统,并且新注册的用户进行单项同步更新。这不是虾扯蛋吗?.....


为什么不可行

为了实现用户信息互通而达到业务要求,其实方案有很多。如果不是底线情况下,同步用户信息这种方案就是一个外行人,一个扯淡的方案。为什么这么说?

首先说信息同步这种方式,如果是单项同步,双方所有相关人员的工作量已经非常之大,一定条件下单项同步升级为双向信息同步,双方的编程人员将会苦不堪言。

另外撇开工作量,用户的信息本质上属于用户的私密信息,一个用户能够把自己的隐私放心的存储在你这里,就说明了对公司的信任度。

一旦发生用户信息复制的操作,本质上是对用户的不负责任,道德上,法律上都有所欠缺。


解决方案

作为一个技术人员,排除不合理方案,提供在业务可行情况下的技术方案是职责所在,那有没有不用复制用户信息这么 low B 的方案呢?

假设我们所在公司的系统为 A,业务的域名为 www.A.com,第三方系统为 B,业务域名为 www.B.com。

记住我们的最终业务目标:允许我们公司的用户(A 系统)在第三方系统(B 系统)能够登录,并且能够获取用户一些相关的信息。极限业务情况下,在 A 系统用户修改了相关信息,并且同步到 B 系统。


解决方案 1

在第三方系统登录的入口,允许我方用户输入账号密码,然后第三方系统(客户端或者服务端都可以)携带用户输入的账号密码请求我司登录服务器。

如果验证通过则返回用户相关信息,第三方系统接收到返回数据,按照自己相关的登录流程进行登录,并且可以存储用户相关的信息。

请求的形式和大体的流程如下图所示:

http://www.A.com/login?loginname=caicai&pwd=buzhidao 


说实话,我并不推荐这种方案,虽然它比直接复制用户信息要好一些,但是依然问题很大,用户在无形中已经把账号密码或者其他登录凭证泄露给并不信任的第三方系统中,而这可能并非用户想要的结果。


解决方案 2

以上方案有一个致命的缺点,那就是登录页面是用户并不信任的第三方页面,如果能避免这样的危险,让用户在信任的我方登录,会大大增强用户的信任度。

技术方面在我方实现登录实在是容易,唯一需要考虑的是用户登录成功之后如何把用户信息发送给第三方系统。

如果采用请求调用的方式(比如:登录成功,我方调用第三方一个接口),技术上可以实现。

但是下次再来一个第三方申请这样的业务,我方的调用接口可能会需要修改,所以现在业界比较好的也比较通用的方式是通过地址的跳转来实现。

具体流程如下:

  • 用户在第三方点击登录,跳转到我方提供的登录页面,页面 URL 中带有登录成功跳转的页面地址,并在此页面输入账号密码。
  • 我方根据用户账号密码判断用户正确性,登陆成功,获取用户信息。
  • 然后跳转到第三方提供的登录成功跳转页面,并把用户信息携带过去。
  • 第三方跳转页面接收到用户信息,处理剩余业务,流程结束。

第一步中第三方跳转到我方的登录页面 URL 如下所示:

http://www.A.com/login?type=userinfo&redirecturi=http://www.B.com/callback 



解决方案 3

方案 2 中登录部分已经和方案 1 有了本质的区别,虽然仅仅是一个登录方的改变,安全性以及对用户隐私的保护上却有着大大的提升。

但是流程中却依然存在着主动传输用户信息,如果有人劫持的话,还是有用户信息泄露的风险。如何避免这样的风险呢?

试想,能否利用其他凭据来代替用户信息呢?当然是可以,这也是现代 Web 系统实现授权的普遍方式。

用户信息取而代之的是一个令牌,而且这个令牌有一定的时效性,只能维持一段时间内有效,这在一定程度上保护了系统数据。

第三方系统获取到这个令牌之后,每次获取用户信息都会携带着这个令牌作为凭证,我方的系统同时也只认可这个令牌作为授权的凭证。

http://www.A.com/login?type=token&redirecturi=http://www.B.com/callback 


这里我要顺便说一下,令牌的下发是通过前端(浏览器)的跳转传输给第三方系统,然后第三方系统的前端传输给后端,然后第三方的后端携带令牌获取用户信息。

要注意哦,如果是第三方前端页面携带令牌去获取用户信息,毫无安全性而言。


解决方案 4

方案 3 其实在很多时候已经足够了,但是有一点需要注意,每个令牌有一定的有效时间,这是设计上的优势,同时也意味着令牌如果被其他人获取到,一样可以窃取用户信息。

由于在方案 3 中令牌的下发实际上还是通过前端(浏览器)来传输的,凡是在前端传输的情况下,就会有泄露的风险,那有没有办法避免在前端传输呢?

这里需要提醒一点,要想实现我方用户可以登录第三方系统,并且在保护用户隐私的情况下,在我方登录是必须的。

而且我方系统必须颁发给第三方系统一个凭证才能达到第三方获取我方用户的要求。

既然传输凭证不可避免,于是人们便想到了可以在前端(浏览器)传输一个只有一次有效的凭证,然后第三方后端依据这个凭证去获取令牌,因为服务端的通信要比前端(浏览器)的通信要安全的多。

于是方案 4 应运而生:

  • 用户跳转到我方登录页面进行登录。
  • 我方验证用户用户名密码无误,产生一个有效次数为 1 并且一定时间内有效的 Code,并携带着这个 Code 跳转到第三方的回调页面。
  • 第三方回调页面,收到 Code 参数,传输给后端程序。
  • 第三方后端程序收到 Code 参数,携带着 Code 调用我方接口。
  • 我方验证 Code 有效性,如果有效则返回令牌信息。
  • 第三方收到令牌信息,携带令牌信息调用我方接口获取用户信息。
  • 我方验证 Token 有效性,如果有效则返回用户信息。
  • 之后的每次调用都携带着 Token 进行访问,Code 就算被人获取到已经不起作用。
http://www.A.com/login?type=code&redirecturi=http://www.B.com/callback 



升级方案

方案 4 虽然看上去已经足够好,但是并非完美。主要表现在如下几点:

①当第三方跳转到我方登录页面的时候,我方并不知道这个第三方是谁,是不是可信任的,所以有必要让我方识别这个第三方是否可以信任。

我方在授权第三方的时候可以给每一个第三方颁发一个类似于 appid 和 appkey 的数据,appid 用来标识每一个我方授权的第三方,而且每一个 appid 必须注册进行回调的 URL。

这样当第三方跳转到我方登录页面的时候,我方就可以识别出来这个第三方以及回调跳转的 URL 是否有效。

②当第三方携带着 Code 去换取 Token,以及之后携带 Token 去获取用户信息的每次通信,都应该按照我方规则利用 appid 和 appkey 进行签名处理,这样我方的服务器端也能够识别出来调用方是否是可信任的。

③在用户登录授权的页面,用户可勾选自己授权给第三方的数据内容,这些权限将作用于 Code 以及令牌中。

④由于每个令牌都有失效时间,如何更新令牌则会是一个技术点,其实完全可以在下发令牌的同时也下发一个用于更新令牌的令牌,这个令牌随着每次重新下发令牌而更新。

⑤我方用户的信息每次更新的时候,可以把相关的令牌失效,以达到让第三方重新获取用户信息而同步的效果。

⑥我方登录页面以及供第三方调用的所有接口都应该采用 HTTPS 协议,并要求所有的第三方回调页面必须也全部采用 HTTPS,这能有效的防止恶性劫持。

原文 http://network.51cto.com/art/201911/606024.htm

链接: https://www.fly63.com/article/detial/6466

CSS定位之BFC背后的神奇原理

BFC已经是一个耳听熟闻的词语了,网上有许多关于 BFC 的文章,介绍了如何触发 BFC 以及 BFC 的一些用处(如清浮动,防止 margin 重叠等)。BFC直译为\"块级格式化上下文\"。它是一个独立的渲染区域,只有Block-level box参与

天天都在使用CSS,那么CSS的原理是什么呢?

作为前端,我们每天都在与CSS打交道,那么CSS的原理是什么呢?开篇,我们还是不厌其烦的回顾一下浏览器的渲染过程,学会使用永远都是最基本的标准,但是懂得原理,你才能触类旁通,超越自我。

JavaScript 中的函数式编程原理

做了一些研究,我发现了函数式编程概念,如不变性和纯函数。 这些概念使你能够构建无副作用的功能,而函数式编程的一些优点,也使得系统变得更加容易维护。我将通过 JavaScript 中的大量代码示例向您详细介绍函数式编程和一些重要概念。

Angular ZoneJS 原理

如果你阅读过关于Angular 2变化检测的资料,那么你很可能听说过zone。Zone是一个从Dart中引入的特性并被Angular 2内部用来判断是否应该触发变化检测

Vue.js响应式原理

updateComponent在更新渲染组件时,会访问1或多个数据模版插值,当访问数据时,将通过getter拦截器把componentUpdateWatcher作为订阅者添加到多个依赖中,每当其中一个数据有更新,将执行setter函数

new运算符的原理

一个继承自 Foo.prototype 的新对象被创建;使用指定的参数调用构造函数 Foo,并将 this 绑定到新创建的对象。new Foo 等同于 new Foo(),也就是没有指定参数时,Foo 不带任何参数调用的情况

彻底弄懂HTTP缓存机制及原理

Http 缓存机制作为 web 性能优化的重要手段,对于从事 Web 开发的同学们来说,应该是知识体系库中的一个基础环节,同时对于有志成为前端架构师的同学来说是必备的知识技能。

https的基本原理

HTTPS = HTTP + TLS/SSL,简单理解 HTTPS 其实就是在 HTTP 上面加多了一层安全层。HTTP 可以是 Http2.0 也可以是 Http1.1,不过现在 Http2.0 是强制要求使用 Https 的。使用非对称密钥(即公钥私钥))和对称密钥)(即共享密钥)相结合

Node中的Cookie和Session

HTTP是无状态协议。例:打开一个域名的首页,进而打开该域名的其他页面,服务器无法识别访问者。即同一浏览器访问同一网站,每次访问都没有任何关系。Cookie的原理是

理解Promise原理

Promise 必须为以下三种状态之一:等待态(Pending)、执行态(Fulfilled)和拒绝态(Rejected)。一旦Promise 被 resolve 或 reject,不能再迁移至其他任何状态(即状态 immutable)。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!