因为新项目涉及到前后端分离,需要前端跳转到授权页,然后后端把授权数据返回给前端。同时考虑高并发下的负载能力,打算把静态页面和后端的服务器(包括域名)分离。
这样就遇到了问题。
前后端跨域
假设我们的前端页面是h5.a.com
后端(微信授权的服务器)为wx.a.com。
首先因为授权需要由微信后台 开发者选项中的域名发起,那么授权之后如何把授权信息给前端页面呢?
1.cookie 跨域似乎并不能设置cookie,当然把cookie的域设置成/理论上是可行的
2.以get参数传递 明文传递似乎容易被篡改用户信息
思考之后,修改为如下
1.授权登录接口
整个操作在后端页面完成,直到获取到用户信息。跳转回活动页,同时在参数中附带当前用户的openid。
2.获取用户信息接口
前端传递openid之后,后端根据该openid从数据库中查找对应的用户信息返回。
这个设计导致了几个问题
1.获取用户接口需要频繁查表,几万的数据量和小规模请求无所谓,量级一大数据库可能会堵塞。
2.因为项目需要获取用户的关注状态,即使非关注状态下也需要返回用户授权的信息。这样 1 接口的授权信息需要额外数据库存储或者被丢失
再次思考修改之后,解决。
解决思路如下
1.每次授权之后 加密openid(md5,sha1之类的,保证token唯一性就好)作为redis的key,然后把本次授权的用户数据存到redis里
2.跳转回活动页,附带上token值。前端以是否存在token作为授权成功的依据
3.前端使用该token请求服务器,获取用户数据。
这样的话
1.使用了redis持久化内存数据库存储数据,写入读取极快。基本不会出现堵塞
2.把用户数据存储到redis之后,可以实现前后端分离,前端每次使用token获取用户数据即可
3.因为保存的是授权信息,而不是从关注用户表中查。即使未关注用户,也能取到他的数据
后记
关于如何实时获取用户的关注状态
因为用户授权不会返回用户是否关注公众号,常规操作是从关注用户表中查询数据。
一种是数据表做好openid索引,提高数据库搜索速度。另一种奇淫异技就是借用微信的获取用户基本信息接口
服务号获取用户基本信息的日接口调用次数为5000W,一般的活动,日PV 5000W次已经不得了,倒那个级别应该会有别的不同的视角去解决这个问题了。
一般的活动几万人参加 日PV也不过100W(参考去年发的某篇文章,日IP10多W,PV也不过80多W),所以5000W这个次数足够一般公司使用了,重点是这个接口调用速度极快,且实时。
区分是否已关注,从返回json里的subscribe属性获取即可
关注状态
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| { "subscribe": 1, "openid": "o6_bmjrPTlm6_2sgVt7hMZOPfL2M", "nickname": "Band", "sex": 1, "language": "zh_CN", "city": "广州", "province": "广东", "country": "中国", "headimgurl":"http://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0", "subscribe_time": 1382694957, "unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL", "remark": "", "groupid": 0, "tagid_list":[128,2], "subscribe_scene": "ADD_SCENE_QR_CODE", "qr_scene": 98765, "qr_scene_str": "" }
|
未关注状态
1 2 3 4 5 6
| { "subscribe": 0, "openid": "o0mOfxJ8r236mPAjxvtu3AIdpITY", "unionid": "o39051qStbZ2WqEFP9Br_iNeedIM", "tagid_list": {} }
|
![]()