当前位置: 首页 > 科技观察

或许,这样更容易理解OAuth的原理吧!

时间:2023-03-17 23:25:47 科技观察

那一年,我公司的用户数量达到了公司成立以来的新高峰。经过众多程序员夜以继日的加班加点,每个业务系统都达到了差不多四九的稳定,同时在业务界也有了一定的知名度。图片来自PexelsPS:以下业务场景仅针对Web系统,Web页面有后台服务程序。那天,一位商业伙伴突然上门拜访,并提出了双赢的合作意向。业务场景是我们的系统用户可以登录他们的系统,从用户那里获取一定的信息,进行一些业务操作。他们希望我们可以将现有用户数据的副本导入到他们的系统中,新注册的用户将进行单次同步更新。这不是扯淡吗。。。为什么不能用来实现用户信息交换,满足业务需求呢?其实解决办法有很多。如果不是底线,同步用户信息的方案就是门外汉,扯淡的方案。你为什么这么说?首先,让我们谈谈信息同步。如果是单项同步,双方所有相关人员的工作量就已经很重了。在一定条件下,如果单项同步升级为双向信息同步,两边的程序员都会很惨。另外,无论工作量大小,用户信息本质上都是用户的隐私信息。用户可以安全地将他的隐私存放在你这里,这表明他对公司的信任。一旦出现复制用户信息的操作,本质上是对用户的不负责任,是道德和法律上的缺失。解决方案作为技术人员,有责任剔除不合理的方案,在业务可行的情况下提供技术方案。有没有不需要复制用户信息的低B方案?假设我们公司的系统是A,业务域名是www.A.com,第三方系统是B,业务域名是www.B.com。记住我们最终的商业目标:让我们公司的用户(系统A)登录到第三方系统(系统B),并从用户那里获取一些相关信息。极端业务情况下,A系统用户修改相关信息同步到B系统。解决方案1、在第三方系统的登录入口,让我们的用户输入账号密码,然后第三方系统(客户端或服务器均可)要求我司使用用户输入的账号密码登录服务器。如果验证通过,则返回用户相关信息。第三方系统收到返回数据后,会按照自己的相关登录流程进行登录,并可以存储用户相关信息。请求的形式和大致流程如下图所示:http://www.A.com/login?loginname=caicai&pwd=buzhidao老实说,我不推荐这种方案,虽然比直接复制要好用户信息,但是还是有很大的问题。用户在无形中将账号密码或其他登录凭据泄露给了不受信任的第三方系统,而这未必是用户想要的结果。方案二上述方案有一个致命的缺点,就是登录页面是用户不信任的第三方页面。如果能够避免这样的危险,让用户登录到我们信任的一方,将大大提升用户的信任度。从技术上来说,我们登录确实很容易,唯一需要考虑的就是用户登录成功后,如何将用户信息发送给第三方系统。如果采用请求调用的方式(比如登录成功,我们调用第三方的接口),技术上是可以实现的。但是下次第三方再申请这样的服务,我们的调用接口可能就需要修改了,所以目前业界更好更通用的方式是通过地址跳转来实现。具体流程如下:用户点击第三方登录,跳转到我们提供的登录页面。页面URL包含登录成功的页面地址,在该页面输入账号密码。我们根据用户帐号和密码判断用户的正确性,成功登录,获取用户信息。然后跳转到第三方提供的登录成功跳转页面,把用户信息带上去。第三方跳转页面接收用户信息,处理剩下的业务,流程结束。第一步,第三方跳转到我们的登录页面URL如下:http://www.A.com/login?type=userinfo&redirecturi=http://www.B.com/callbackSolution32中的登录部分与方案一有本质区别,虽然只是改变了登录方,但是在安全性和用户隐私保护方面都有了很大的提升。但是,这个过程中仍然存在用户信息的主动传输。如果有人劫持,仍然存在用户信息泄露的风险。如何规避此类风险?试想,是否可以用其他凭证来代替用户信息呢?当然可以,这也是现代Web系统实现授权的常用方式。用户信息被一个token代替,这个token具有一定的时效性,只能在一段时间内有效,在一定程度上保护了系统数据。第三方系统获取到这个token后,每次获取用户信息都会携带这个token作为凭证,而我们的系统也只把这个token识别为授权凭证。http://www.A.com/login?type=token&redirecturi=http://www.B.com/callback这里我想顺便说一下,token是通过前端(浏览器)的跳转传输发出的)到第三方系统,然后第三方系统前端传输给后端,然后第三方后端携带token获取用户信息。注意,如果第三方前端页面携带token获取用户信息,是没有安全保障的。方案四,方案三其实在很多情况下就够用了,但是有一点需要注意,每个token都有一定的有效时间,这是一个设计优势,也意味着如果token被别人拿到了,同一个User信息可能被窃取。由于方案3中代币的发行实际上是通过前端(浏览器)传输的,所以在前端传输的情况下存在泄露的风险。有没有办法避免在前端传输?在这里我们需要提醒一下,为了实现我们的用户可以登录第三方系统,在保护用户隐私的情况下,有必要使用我们的登录方式。而且,我们的系统必须给第三方系统颁发证书,才能满足第三方获取我们用户的要求。由于证书的传输是不可避免的,所以人们认为可以在前端(浏览器)传输一个只有一次有效的证书,然后第三方后端根据这个证书获取token,因为服务器的通信比前端(浏览器)更快。通信更加安全。于是方案4应运而生:用户跳转到我们的登录页面登录,我们验证用户的用户名和密码是否正确,生成一个有效计数为1且在一定时间内有效的code,跳转使用此代码到第三方回调页面。第三方回调页面接收Code参数,传给后台程序。第三方后台程序接收Code参数,用Code调用我们的接口。我们验证Code的有效性,如果有效则返回token信息。第三方接收token信息,携带token信息调用我们的接口获取用户信息。我们验证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和token。④由于每个token都有过期时间,如何更新token将是一个技术点。实际上,可以在发行令牌的同时发行更新令牌的令牌。每次重新发行令牌时都会更新。⑤每次我们的用户信息更新时,可以使相关的token失效,达到让第三方重新获取用户信息并同步的效果。⑥我们的登录页面和所有第三方调用的接口都应该使用HTTPS协议,所有的第三方回调页面也必须使用HTTPS,这样可以有效防止恶意劫持。不知道有没有教过对author2.0授权不清楚的同学。如果还有不懂的,欢迎在下方留言交流。