最近开发微信小程序,做登录功能时遇到下图。
看太懂,有几处疑惑地方:
下面就是寻找答案的过程。
豪车模型
邻居模型
在上面两个模型中。豪车的主钥匙赋予泊车钥匙部分权限,而你赋予你的邻居所有的权限。比较之下,我们更希望使用豪车模型赋予部分权限,而不是邻居模型,万一他偷偷配了把钥匙呢?这种授权存在不安全性,在网络开发中也是如此。
登录时可以选择社交账号登录,这里以 QQ 为例。这里涉及三方:当前要登录的用户,以下简称 用户 ,其它两方是: , QQ 服务器 。因为 用户
之前注册过 QQ, 请求 QQ 服务器 授权用户的 QQ 基本信息,这样用户就不用在上再进行注册了。
下面来探讨下 QQ 服务器 如何授权 当前 用户 的 QQ 基本信息。
这种方法比较简单, 用户 告诉 它的 QQ 账号密码,拿着账号密码去请求 QQ 服务器获取用户基本信息。
优点 : *** 作简单。
缺点 :用户将 qq 账号密码给了,获得了该用户在 QQ 上的所有特权,不仅可以查看基本信息,还可以查看 QQ 空间,查看 QQ 邮箱等,而用户的本意是只让获取 QQ 基本信息这一项特权。
下面是在 小胡子哥的个人博客 里看到的,将整个授权过程讲解的生动形象,我就不做二次加工,直接截取部分内容如下。
开发微信小程序第一步要在 微信公众平台 上注册一个账号,注册完成后在 设置 > 开发设置 里可以看到 AppID 和 AppSecret,这相当于上面提到的 Client Id 和 Client Secret。
微信登录用户 在 微信 中打开 小程序 , 小程序 中运行了 wxlogin 接口,此时 小程序 拿着 appid 去请求 微信服务器 给 小程序 授权,让它可以调用一些微信接口,比如获取微信登录用户的基本信息。因为是 微信登录用户 进行 *** 作的,所以微信那端默认是同意授权的。(appid 哪里来?在新建小程序项目时输入,每个 appid 和小程序都是一一对应的)
上面也提到,这个 code 可能会泄露,所以需要 code + appid + appsecret 去再次拜访微信服务器获取令牌 session_key 和用户标识 openid。
这里有个疑问?为什么获取 code 在小程序上做,而获取 session_key 在第三方服务器上 *** 作?这是因为获取 code 需要使用 appid 去跳转微信服务器授权页面,再使用当前 微信登录用户 默认同意此次授权,如果坐在第三方服务器上,appid 我们是知道的,但是当前 微信登录用户 是不知道,只要手机上的微信知道。
那为什么请求 session_key 在第三方服务器上 *** 作?这是因为前面也说过 code 只能表明微信服务器统一此次授权,但是 code 可能会泄露,还需要第二张门票 appsecret 告诉微信服务器 “就是我,不是别人” 来请求获取 session_key 的。可见 appsecret 对于安全的重要性,放在第三方服务器方便管理。
关于 openid 和 session_key 说明?session_key 就是返回的绿卡,此后每次访问微信服务器资源都要带上它,这样微信服务器才知道此次请求是有授权的,我可以把资源给你。openid 是同意授权的那个人,这里是 微信登录用户 的标识 ID。也就是为什么 code 要在小程序中获取中我们不知道的那个 微信登录用户 ID。
到此,上图中涉及 Oauth20 的部分已经结束,下面的那些都是普通的 session 维持会话机制,这里就不再赘述。
由于作者文笔有限,文章如有遗漏或表达有误,请不吝赐教。如果仍对微信授权或 Oauth20 有疑问的,欢迎留言讨论。
小程序登录第一次总是会失败,第二次肯定成功pad block corrupted
<meta charset="utf-8">
在开发微信小程序过程中,遇到一个登录的问题。就是微信小程序登录 *** 作的时候,第一次总是会失败,返回 pad block corrupted ,然后再次登录的时候就会登录成功。出现这样的错误,百度原因大多数是说 session_key 过期,到期去解密手机号数据的时候,解密出错。具体分析:
img
这里描述的问题是出现在第四步的步骤中,原因是第三步获取的 session_key 不正确,导致解密 *** 作错误,返回 pad block corrupted 。但是导致 session_key 不正确的原因是第二步调用 wxlogin() 方法,会刷新 session_key 。因为第一步获取的手机号加密数据是通过原来的 session_key 加密的,现在 session_key 刷新了,导致后台在第三步去获取 seesion_key 的时候,获取的是新的 seesion_key ,然后去解密的时候就报错了。
1、可以使用小程序的storage本地存储功能,将用户在底部导航栏点击的内容存储在storage中,开发者可以在每次用户进入小程序时,获取storage中存储的信息,实现自定义底部导航缓存。
2、也可以使用小程序的session本地存储功能,将用户在底部导航栏点击的内容存储在session中,开发者可以在每次用户进入小程序时,获取session中存储的信息,实现自定义底部导航缓存。
3、可以使用小程序的openid,将用户在底部导航栏点击的内容存储在openid中,开发者可以在每次用户进入小程序时,获取openid中存储的信息,实现自定义底部导航缓存。
4、也可以使用小程序的云数据库,将用户在底部导航栏点击的内容存储在云数据库中,开发者可以在每次用户进入小程序时,获取云数据库中存储的信息,实现自定义底部导航缓存。
微信小程序获取用户信息的接口确实已经被封了,因此现在需要使用微信登录的方式进行用户身份验证和获取用户信息。在小程序中首先通过wxlogin()接口获取用户登录凭证code,然后在小程序后台配置开发者服务器地址和域名,在开发者服务器端使用code请求微信服务器获取openid和session_key等信息。之后就可以得到openid等用户信息并存储到开发者服务器端进行相关业务逻辑处理。同时需要注意需要在小程序中进行用户授权,以获取用户允许授权后的信息。
很多小菜鸟们在使用比如vue的axios对后端进行异步请求时候,比如做到关于注册的验证码的业务时候,明明在后端存进了session时候,但是第二次请求另一个接口的时候session取不到了(null),那是因为前端在请求的时候没有带上cookie,对于后端来说就产生了两个不同的session
那这种情况怎么解决呢?
拿微信小程序举例来说
1、首先我们可以全局设置一个空cookie
2、在第一次请求的接口中获取这次用到的session的id并且作为数据返回
3、在微信小程序中处理业务的js中接受返回的id并且赋值给cookie
4、在第二次请求的时候将cookie封装到请求头中
这样子呢,这种简单粗暴的方式就可以解决不同controlle会产生不同的session的问题啦
1、appid: 微信小程序/公众号的唯一凭证,即 AppID。
获取途径:可在「微信公众平台 - 设置 - 开发设置」页中获得。(需要已经成为开发者,且帐号没有异常状态)
用途:小程序的 AppID 相当于小程序平台的一个身份z,会在很多场景中使用,比如小程序的登录、授权等
2、openID: openID 是微信生态下 应用的唯一标识 , ,即同一个用户在不同的小程序下的openid是不同的。
获取途径:调用 authcode2Session 接口,通过code(登录凭证,调用wxlogin获取)+appid+appsecret(小程序密钥,获取方式和appid一样)可以换取openid,即 静默授权。
用途:用于在开发者系统中标识用户信息
3、UnionID:UnionID 是微信生态下 用户的唯一标识 ,换句话说,同一用户,对同一个微信开放平台下的不同应用,UnionID是相同的。
获取途径:绑定了开发者帐号的小程序,可以通过以下途径获取 UnionID。
1)开发者可以直接通过 wxlogin + code2Session 获取到该用户 UnionID,无须用户授权。
2)小程序端调用云函数时,可在云函数中通过 CloudgetWXContext 获取 UnionID。
用途:标识同一个微信开放平台下的用户,可用于去重判断
也就是我们常用的微信移动端/PC端之间的扫码登录,PC端用微信扫码登录,微信移动端确认授权登录后,应用可以从微信拿到用户的open id或union id,将微信获取的用户信息与自己账户体系中的用户身份进行关联;
需要用户确认登录,这样可以通过用户的个人确认,获取用户全面的信息,无论是否关注相关微信公众号等都可以获取。
1、静默授权不需要用户确认,只需要用户访问某个网页,属于嵌套在普通网页里的授权形式,但是只能获取到用户的唯一标示openid和union id,无法拿到用户的微信头像、微信名称等个人信息,对于用户的简单认证还是很有用的。
2、静默授权的过程:
1)调用 wxlogin() 获取 临时登录凭证code
2)调用 authcode2Session 接口,换取用户唯一标识 openID
3)调用本地后台服务,将 openID 映射到本地的 userId
微信开发文档-小程序登录流程
参考文章:
1、 微信小程序用户授权登录
2、 微信第三方登录(静默授权和非静默授权)
3、 openid会变吗?微信小程序开发中的appid、openid、unionid使用总结
通过wxgetUserInfo获取用户的openId 和unionId,需要对接口返回的加密数据( encryptedData )进行对称解密。
/
功能描述: <br>
〈功能详细描述〉
@paramargs
@see[相关类/方法](可选)
@since[产品/模块版本](可选)
/
publicstaticvoidmain(String[] args){
String encryptedData ="";
String sessionKey ="";
String iv ="9btKSYjvtGMGpknPpjS2Ag==";
JSONObject jsonObject = getUserInfo(encryptedData, sessionKey, iv);
Systemoutprintln(jsonObjectgetString("unionId"));
Systemoutprintln(jsonObjecttoJSONString());
}
结果运行报错:
javaxcryptoBadPaddingException: pad block corrupted
at orgbouncycastlejcajceprovidersymmetricutilBaseBlockCipher$BufferedGenericBlockCipherdoFinal(Unknown Source)
at orgbouncycastlejcajceprovidersymmetricutilBaseBlockCipherengineDoFinal(Unknown Source)
at javaxcryptoCipherdoFinal(Cipherjava:2087)
at comsaicebizserviceutilAESUtilsgetUserInfo(AESUtilsjava:62)
at comsaicebizserviceutilAESUtilsmain(AESUtilsjava:86)
Exception in thread"main"javalangNullPointerException
at comsaicebizserviceutilAESUtilsmain(AESUtilsjava:87)
查询原因,有可能是我的wxlogin在wxgetUserInfo之后调的原因,细究一下
我们通过wxlogin获得用户授权码code,接下来我们用code以及appid和appSecret请求微信
>
本文以抖音小程序(微信小程序获取流程和接口一模一样)为例,最近博主在做一个抖音小程序的小项目,前端在获取用户手机号的时候,需要调用 ttlogin 接口进行登录,登录后返回一个code,这个code有3分钟的失效时间,根据这个code可以获取到sessionKey,这个sessionKey类似于对称加密的密钥,会对用户信息进行加密。在获取用户信息的时候,前端
需要将 <button> 组件 open-type 的值设置为 getPhoneNumber。用户点击后会d出一个授权d窗让用户确认(若该用户账户未绑定手机号码会执行一次绑定手机号码的流程;授权d窗每次使用都会d出)。 用户同意后,开发者可以通过 bindgetphonenumber 事件回调获取到一个加密数据,开发者可以把该数据传回到自己的服务端进行解密获取手机号。
获取到的加密数据需要使用sessionKey进行解密,因此在获取用户信息前,需要登录一次,获取到code,然后根据code获取到sessionKey,再根据sessionKey进行加密数据的解密,解析出手机号。
根据博主猜测,抖音在登录后会生成一个code,和一个对应的sessionKey,在会话期间(session未过期)的时候获取用户信息,会将用户信息使用sessionKey进行数据的加密,进行数据的解密也需要使用到sessionKey。code和sessionKey是对应的,但是它们的失效期是不一样的,code的失效期是3分钟,sessionKey的失效时间是不定的,只要用户活跃在页面上都不会失效。在获取到code的3分钟内调用 code-2-session 接口,会获取到sessionKey,如果3分钟后根据code获取sessionKey将会获取失败,因此解密也会失败。
因为无法判断用户什么时候开始获取用户信息,所以用户一进入页面,前端就会调用 ttlogin 接口进行登录,然后放到localstorage缓存中,在用户点击按钮时,d出授权框用户确认后获取到用户信息的加密数据,然后前端将缓存的code和加密数据一并传给后端。后端用code先去调用 code-2-session 接口获取到sessionKey,然后以sessionKey为密钥进行AES解密,获取到手机号返回给前台。整个流程看起来没什么问题,但是一旦用户在页面停留时间超过3分钟,然后再去获取用户信息会失败,主要是因为code已经失效,获取sessionKey会失败。
目前的问题就是过了code的有效期后,根据code获取sessionKey失败。那么在前端login获取到code后,先缓存到本地,然后立即调用后台接口去获取sessionKey然后缓存到redis里面,key为code,value为sessionKey。失效时间根据自己的业务设置(小程序页面用户不会停留太久,因此缓存失效时间设置为30分钟),用户退出小程序后,会重新login,然后也会存一份新的code和sessionKey的对应值。
用户在授权到用户信息后,前端直接将缓存的code和加密后的用户信息上传到服务到进行解密。服务端根据code从缓存中先获取到sessionKey,然后再用sessionKey进行解密,解析出手机号进行返回。
以上解决办法每次基本都可以获取手机号成功,但是也会存在一些问题
UserInfoController主要提供两个接口,一个是解密手机号和code2seesion *** 作
TiktokEncryptedParam 主要是前端传过来的code和加密后的数据
TiktokUserInfoSPI 主要是对接口的封装
TiktokUserInfoSPIAdapter 实现接口
使用AES对称加密
以上就是关于梳理微信小程序登录时序图:授权与 Oauth2.0全部的内容,包括:梳理微信小程序登录时序图:授权与 Oauth2.0、小程序第一次登录失败,第二次成功问题(2)、小程序自定义底部导航缓存等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)