1.小程序登录
数据流梗概:
1.客户端登录(产生res.code)
2.APP服务端(持有appid\appsecret)
3.微信服务(appid+appsecret+res.code换取sessionKey、openid、unionid)
4.APP服务端(存储微信服务返回的openId、unionid等,产生自定义的sessionId)->
5.客户端登录完成(持有sessionId,每次请求发回服务端)
小程序前端登陆:
1 | const login = async() => { |
后台代码:(注:非真实后端代码,但原理一样。)
1 | router.get('/wx/onlogin', function (req, res, next) { |
这段后台代码成功执行的话,就可以得到openid和session_key。这个信息就是当前微信账户在微信服务器那边的登录态了。
但是,为了安全方面的原因,请不要直接使用这些信息作为你小程序的用户标识和session标识回传到小程序客户端中去,我们应该在服务器端做一层自己的session,将这个微信账号登录态生成一个session id并维护在我们自己的session机制中,然后把这个session id派发到小程序客户端作为session标识来使用。
关于如何在服务器端做这个session机制,我们现在一般采用键值对存储工具来做,比如redis。我们为每个session生成一个唯一的字符串作为键,然后可以将session_key和openid作为值,存入redis中,为了安全,存入的时候还应设置一个超时的时间。
开发Web应用的时候,在客户端(浏览器)中,我们通常将session id存放在cookie中,但是小程序没有cookie机制,所以不能采用cookie了,但是小程序有本地的storage,所以我们可以使用storage来保存sessionid,以供后续的后台API调用所使用。
在之后,调用那些需要登录后才有权限的访问的后台服务时,你可以将保存在storage中的sessionid取出并携带在请求中(可以放在header中携带,也可以放在querystring中,或是放在body中,根据你自己的需要来使用),传递到后台服务,后台代码中获取到该sessionid后,从redis中查找是否有该sessionid存在,存在的话,即确认该session是有效的,继续后续的代码执行,否则进行错误处理。
这是一个需要session验证的后台服务示例,我的sessionid是放在header中传递的,所以在这个示例中,是从请求的header中获取sessionid:
1 | router.get('/wx/products/list', function (req, res, next) { |
openID: 普通用户的标识,对当前开发者帐号唯一。一个openid对应一个公众号。
UnionID :用户统一标识。针对一个微信开放平台帐号下的应用,同一用户的unionid是唯一的。
如果用户已经关注公众号,或者曾经登录过App或公众号,则用户打开小程序时,开发者可以直接通过wx.login获取到该用户UnionID,无须用户再次授权。
这里分为两种情况,
(1)用code换取的时候,返回了unionid,这样就皆大欢喜了,你可以根据unionid以及openid去判断该用户有没有用户信息,从而获取userid或者生产userid返回给前端
(2)悲剧的情况,unionid返回为null,这时候你没法儿关联出用户的userid。后来再去看官方文档的时候,发现有针对这种情况的方法。就是需要前端再去调wx.getUserInfo()这个接口。这时候微信会返回很多数据详情见微信官方文档:,这些数据里面有一个encryptedData,这个数据中就包含你需要的unionid以及其他的很多用户信息啦。获取到以后将encryptedData、加密算法的初始向量iv返回给后端,后端根据这两个数据以及之前的session_key就可以解密出你需要的数据了。
encryptedData 解密后为以下 json 结构,
1 | { |
2.获取用户信息
在此之前,小程序获取微信的头像,昵称之类的用户信息,我用的都是wx.getUserInfo,例如
1 | onLoad: function (options) { |
wx.getUserInfo需要用户授权 scope.userInfo,也就是那个授权弹窗。
但自从微信接口有了新的调整之后 这个wx.getUserInfo()便不再出现授权弹窗了,需要使用button做引导~
1 | <!-- 需要使用 button 来授权登录 --> |
1 | //js |
这就是等于一步变两步了~现在用button的话 可以在产品上多加引导,不会显得那么突兀的出来一个弹窗了
然鹅,如果你仅仅只是想展示用户信息的话,那便使用open-data 吧,这样的话,js也就获取不到open-data的值,如下:
1 | <!-- 如果只是展示用户头像昵称,可以使用 <open-data /> 组件 --> |
后记补充:
参考: