通过微信扫码登录剖析 oauth2 认证授权技术

Posted 张子行的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通过微信扫码登录剖析 oauth2 认证授权技术相关的知识,希望对你有一定的参考价值。

本文目录

前言

相信很多小伙伴在学习 JAVA 的过程中或多或少接触或者开发过类似于 xxx 管理系统的这么一个项目。里面的需求很经典也很值得去深究一下,由于早期的互联网环境比较落后,基本上一个单体项目便可吃天下无敌手了,用户需要使用这个系统,提供用户名、密码登录(登录成功授予对应用户相应的权限)即可。后来随着用户数目的暴增,单个项目扛不住这么高的并发了,便想到了相似代码逻辑的几个服务丢到不同的服务器上去运行,这样就减轻了服务器的压力了,但是也会伴随的衍射出一些问题。怎么保证多个服务运行过程中的数据一致性、数据如何共享、分布式事务的一致性…?为了解决这些问题 Redis、TCC、Spring Security…这些技术横空出世!技术是学不完的,但是他们的本质都是服务于项目,而项目必然逃不开 CAP 理论。基于 CAP 理论又衍射出来了一些优秀的架构模式典型的有 NACOS 中的 AP、CP架构),而我们开发者利用这些优秀的架构理念又来开发更高效好用的技术框架,到最后学来学去你会发现这压根就是一个闭环。好了废话就说到这了,接下来开始步入正题:oauth2授权认证技术

趣味解读oauth2

官网对 oauth2 的介绍晦涩且抽象,我拿我切身经历过的一个例子来说。在我找到工作之前物色了很久的房子,挑来挑去终于挑中了一套房子,于是和房东 1.签定了合约,过几天我提着行李箱准备入住的时候,发现房间还没装修完,于是乎我打电话问房东什么情况?房东说:别着急嘛,这样你先住房子旁边的酒店好不,不用出房费,因为这个酒店是我开的。嘻嘻(#.#)。于是乎我急匆匆的挂完电话,提着行李箱,来到酒店前台和小姐姐说,你老板让你给我免费开个房间(速度),小姐姐满脸嫌弃的看着我,内心 OS (空口无凭的还 2.想免费使用我们的房间?)。3.于是乎我随机拨通了房东的电话,并将电话递给小姐姐,让房东和他解释。这样我就 4.可以免费使用酒店的房间 了。注意我从想入住到入住实现的这个过程中经历了些啥,然后下文我会利用 oauth2 来模拟这些过程,帮助大家更好的去理解 oauth2 里面的设计精髓

oauth2精髓

通过趣味解读可以总结出一句话:oauth2能让第三方系统在不知道用户主系统的账号信息的情况下,和用户拥有同等的权限进行操控主系统。换言之就是,别墅虽然是你的、房产证也在你手上,但是如果你同意让我免费蹭别墅住,我也能像你一样住别墅的,注意哦,只是让你同意让我入住,并没有要求房子还要过户给我,房产证还是你的。

oauth2核心概念

结合趣味解读oauth2中的小例子得出

  1. 资源服务:房东要有一座酒店
  2. 认证服务:房东要通过某种方式去通知前台小姐姐,这个客人可以免费入住
  3. 绑定关系:我们去入住酒店的前提,是与房东签订好了合约,合约记录了 xxx 可以入住 xxx 号房,不然我们与房东都没有契约关系,再去叫房东办事,房东都不认识我们自然无法入住酒店了,除非我们出房费

结合微信登录深刻理解oauht2

接下来再结合实际分析一波oauth2中的授权码模式,第三方应用程序接入微信登录功能就是一个不错的例子。不知道大家有没有想过,我们为什么要对接微信登录这个问题? 其实就是为了省钱,开发一个认证中心需要大量人力财力维持,对接微信这种权威的平台,可以减轻我们的开发压力,同时又能获取到用户的真实信息,再落库到本地不香吗。实际的一般开发当中,我们用不着写什么资源服务、认证服务,因为我们的角色是那个第三方应用程序,除非我们在开发微信、QQ这种项目,需要向别人暴露一些接口使用,这个时候就需要考虑该怎么去实现oauht2了,一般开发当中我们用到oauth2协议的地方,就是去对接第三方应用的时候用的多,比如下文要说的微信扫码登录。


上图步骤属实有点繁琐,不妨拆分着来研究一下码云的微信登录逻辑吧。

  1. 当我们在第三方网站使用微信登录时,我们利用微信提供的 js 工具类向微信发起一个请求,表明我要生成一个微信登录的二维码。这么多小网站都在使用微信登录这个功能,生成的二维码要具有一些唯一性(二维码就是一个url,扫码其实就是访问二维码对应的url),因此我们发起请求的时候会附加一些条件:appid:应用id标识符、redirect_uri:回调地址(授权码回调的地址)、response_type:指定是使用oauth2的哪种模式、scope:作用域(只是想获取微信登录相关权限)。其中appid对于不同的应用来说都是唯一的,因此二维码的唯一性就得到了保障。

  2. 发起步骤 1 请求的同时,微信二维码前端页面实际上还在不停的进行轮训,去请求微信服务器上获取 code 的接口(如果轮训到用户扫码的操作了,会提示扫描成功,如果进一步用户在手机上点击了确认登录,pc端会返回 wx_code,之后页面会经过一系列操作将 wx_code 作为 url 参数重定向到我们配置过的 redirect_uri 上面)。这时候可能有人站出来说,这样会不会导致服务器压力过大啊!人家前端是每隔几秒去发起一次这样的请求,就相当于多了几个人去浏览微信官网一下。等我们码云的页面获取到 code 后,再拿着 code 去调码云后台服务器上获取用户信息的接口(这个接口可以通过 code +秘钥获取 token,再通过 token 去调微信提供的获取用户信息的接口…)这里面的业务逻辑大家自行扩展。然后拿着获取到的用户信息重定向回码云的主界面。

  1. 用户在手机上点同意码云申请使用你的昵称头像…后,由于此时code已经重定向到码云指定页面的 url 上面了,码云的 pc 端页面获取到 code,将code作为参数,传给码云服务器,去申请token。然后前端拿到这个 token 就可以做操作了

  2. 到此整个流程结束

本文小结

  1. 由于我们扫码确认登录是在手机端完成的,一般来说手机端点击确认登录后,手机端在微信已经登录的情况下,显然是可以获取到 userId 的,且 pc 端的二维码是利用微信提供的一个 js 类来生成的,为了保证二维码的唯一性,微信会将唯一的一个 uuid 与之绑定,手机端扫码其实就是访问带有 uuid 参数的 url 。如果手机端同意授权登录,那么微信会将 uuid 与 userId 绑定。

2. 通过第一点可以得出 uuid 与 openId 的区别,uuid: 微信号绑定后才有的标识,对于任何应用该微信账号的 uuid 均相同。同一个微信账号不同的应用 uuid 相同。 openid: 微信号对于每个应用均有一个不变的 openid,同一个微信账号不同的应用 openid 不同。
3. 既然 uuid 与 userId 都绑定了,在向微信所要 token 的时候,我们通过微信返回给我们的 unionid 是不是就可以获取用户的资料信息了

4. 微信通过回调 redirect_url 将 code 返回给第三方页面,redirect_url 可以为一个页面地址 或者是 一个接口来接收 code,但是 redirect_url 中的授权回调域名一个应用只能指定一个,如果多个应用程序都需要使用微信扫码登录,但是服务却部署在不同的域名下面,那么要向微信注册多个开发应用(最大数量是10个),所以我们用接口接收 code 一般是用来解决: 微信扫码登录只能填一个授权回调域的问题。解决思路:回调 redirect_url 后面多拼接几个参数,假设应用 A、B都使用微信扫码登录,A设置 redirect_url= https://www.sum.com/redirect?serverUrl=https://www.sum.a.com&name=a,应用 B 设置 redirect_url= www.sum.com/redirect?serverUrl=www.sum.b.com&name=b。我们指定的开发应用的授权回调域名是 www.sum.a.com,符合规则,www.sum.com下的 redirect 接口接收到 code 之后,在把请求转发到 serverUrl 的服务上,同时请求附带 code 参数

以上是关于通过微信扫码登录剖析 oauth2 认证授权技术的主要内容,如果未能解决你的问题,请参考以下文章

Java实现微信扫码登录

Spring Boot 实现微信扫码登录,真香。。

Spring Boot 实现微信扫码登录,真香。。

第三方登录:微信扫码登录(OAuth2.0)

微信开放平台开发——网页微信扫码登录(OAuth2.0)

微信开放平台开发——网页微信扫码登录(OAuth2.0)