很多人在开发微信小程序时,对于微信提供的session_key和access_token很可能处于迷糊状态,总是无法整理清楚两者的区别和用处,在此我总结一下:
session_key是标记用户使用小程序的登陆态的标识。
access_token是小程序服务需要访问微信服务的鉴权标识。
你可能不理解这个意思,没事,接下来详细阐述其作用
session_key
小程序或者小游戏用户,大多数小程序使用时是不是要区分用户(除开一些工具类的小程序),不然用户第二次进入我们的小程序,你怎么知道他是同一个用户?有的开发者说,可以开发一套用户登陆系统啊,让用户登陆之后,把我们服务器的session_cookie或者token放在小程序的本地存储中,这样在服务器中每次就可以获取到用户信息了,这种功能类似于web端的登陆功能。
确实在小程序中你是可以实现这一套自定义的登陆系统的,但是它有一个很严重的缺陷,就是用户清除缓存,或者用户更换手机,或者微信重新安装,等等这种本地状态丢失的情况下,你需要用户又重新登陆。
而且有可能还会导致一个客户会产生多个账号的问题,即如果你不让用户输入一些唯一标识的账号,比如手机号码,那么用户可以用一个客户端注册多个账号,多个账号会导致一些不确定的问题,如果加入手机号码验证其唯一性,那么验证码的功能又要加上,增加了逻辑和成本。
其实微信提供了一个微信登陆态的功能,即你使用微信的登陆态,可以作为你小程序的用户的登陆态,逻辑如图:
客户端使用wx.login来获取code,然后传递给我们自己的小程序后端,在我们自己的小程序后端中,我们需要调用微信服务器的服务,api名为code2Session,它的名字非常形象,通过code获取session,这个接口需要的参数是appId,appSecret,code等,它返回了openId和session_key
这里最重要的就是openId,干了这么多工作,最主要的目的就是为了它,它就是用户唯一标识,类似用户的微信号一样统一,无论用户更换手机或者重装微信,他只要使用同一个微信使用你的小程序,那么这个openId都是唯一的,这样我们自己的服务器,需要利用这个openId来识别用户,你可以将其作为用户主键,或者作为用户表的某个字段,且添加唯一索引,来标识用户等等,这样就实现了用户的区分。
还有一个unionid,它是将多个不同的微信应用,对同一个微信账号统一的id,因为不同小程序的同一个微信用户的openId不一样,这个时候可以考虑使用unionid,只需要将多个微信应用绑定到同一个开发平台账号下。
session_key的目的就是标识当前用户在微信上使用你的小程序的session信息,这个session信息的过期时间微信没有公布,微信的意思是你可以自己定义一个自定义登陆态,来自己控制用户登陆过期机制,当然你也可以使用微信的api,来验证微信的登陆态是否过期,微信提供了两套api:客户端的api和服务器的api。
-
客户端使用
wx.checkSession来检查当前微信用户的登陆态session是否过期,如果过期,你就需要再重新获取code,再重走登陆流程。 -
服务器api是使用接口名为:
checkSessionKey的接口,需要参数:access_token,openId,session_key,这里的access_token,我们暂时不表,你只要记得,它是一个调用凭证。 如果checkSessionKey的接口检测到session_key过期,也是需要重新进行客户端的登录流程。 -
自定义登陆态,是当获取到微信的
session_key之后,我们想自己控制用户的登陆态过期机制,你可以再自定义一个session或者token,然后通过这个session或者token的过期时间,来确定是否需要重新运行客户端重登陆的逻辑,同时这个流程中还需配合检查session_key是否过期的逻辑。
这么看其实session_key的作用非常有限,它仅仅是一个标识,没有什么用处,只有在调用微信服务器的checkSessionKey接口时才会用到,如果你不使用checkSessionKey接口,session_key对于我们来说完全没用。
access_token
说完session_key,我们再来看access_token,这个东西看它的名字,我们就知道他和session_key的不同,它应该是一个token,关于session和token的区别,我想大多数人应该都知道,最大的区别是存储的位置,为什么这个地方要用token了,不用session呢,这是因为access_token的使用场景导致的。
微信服务器提供了很多api,供我们的程序的后台服务器调用,这些api都比较涉及到数据安全和微信的一些服务,比如:支付,直播,手机号码获取等等,这些服务不可能直接让客户端直接调用,微信期望是小程序服务器去调用,这样方便管理和数据统计且安全。
即然是让用户的服务器调用微信的服务,需要区分不同的小程序服务器,且不是任何服务都能调用微信的服务的,所以你需要在调用微信的服务器之前,获取微信给你的access_token,然后以后你调用微信的所有后台服务都得带上这个access_token,又由于是服务器之间相互调用,所以一般私密性比较高,所以可以使用token将数据存储在用户的服务器上,这样可以节省微信服务器的存储资源。
code
有的同学可能很好奇,为什么获取openId和session_key还要在客户端调用一次wx.login呢?
可以直接获取微信的登陆态啊,其实这个考虑率了数据的安全性问题。
首先,要限制这个登陆态的获取必须要在微信小程序中才能获取,不然就可以直接在web端获取到微信的登陆态
其次,微信服务器还需要知道当前微信使用者的信息,所以wx.login肯定需要发送请求给微信服务器
- 第一个目的是让服务器知道当前微信使用者
- 第二个是需要客户端sdk配合服务器一起计算出code标识,来确定当前应用是在微信内使用
当然这个计算code的客户端sdk很重要。由于有网络请求,这也是为什么wx.login会被设计成一个回调函数的方式调用的原因。