//获取用户信息,传递的是一个回调函数,获取到用户信息后执行回调函数,传入的参数是userInfo getUserInfo: function (cb) { const _this = this ; wx.checkSession({ success: function () { let userInfo = wx.getStorageSync( 'userInfo' ); //先从内存中获取userInfo if (userInfo.result == 1 ) { _this.refreshSession(cb); } else { _this.userLogin(cb); } }, fail: function () { _this.userLogin(cb); } }) },
上述方法的参数是一个回调函数,不同的页面在获取了userInfo以后传入不同的回调函数,回调函数的参数就是要获取的userInfo。
首先,调用wx.checkSession()方法判定小程序端登录态是否失效,失效的话则去执行userLogin(cb)操作,未失效则从缓存中去拿userInfo数据。在userInfo中,我们主要存放的是userName,userFace等用户数据和SESSION,还有一个标志位result,用于判断userInfo缓存数据是否失效。
然后,如果我们能从缓存中拿到用户数据,就要 检验服务端的登录态是否通过。访问refreshSession(cb)方法。代码如下
//检查服务端session是否过期 refreshSession: function (cb) { const _this = this ; let userInfo = wx.getStorageSync( 'userInfo' ); wx.request({ url: _this.domain + _this.api.xcxCheckSessionReq, method: 'GET' , header: { 'Cookie' : 'JSESSIONID=' + userInfo.SESSION + ';SESSION=' + userInfo.SESSION, }, success: function (res) { if (res.data == 1) { _this.globalData.userInfo = userInfo; typeof cb == "function" && cb(_this.globalData.userInfo); } else { wx.removeStorageSync( 'userInfo' ); _this.userLogin(cb); } }, fail: function () { wx.removeStorageSync( 'userInfo' ); _this.userLogin(cb); } }) },
此处,调用服务端的接口来验证服务端的session是否已经过期,服务端的代码如下:
public String xcxCheckSession() { Integer result; HttpServletRequest req = ServletActionContext.getRequest(); HttpSession s = req.getSession(); if (s.getAttribute( "c_userId" )!= null ){ result=1; } else { result=0; } OutPutMsg.outPutMsg(result.toString()); return null ; }
其中OutPutMsg方法就是将结果响应给客户端。
上述代码根据小程序端传过来的JSESSIONID或者SESSION的值,利用servlet的特性,根据这个值去获取session,再判断session中是否有用户信息。从而完成服务端的登录态校验。其实原理跟我们在服务端使用拦截器校验session是否过期是一样的。
若服务端登录态校验失败,则需要清空缓存中的userInfo信息,然后去执行userLogin(cb)方法,进行登录。
2.登录操作涉及到小程序端和服务端,小程序端的代码如下:
userLogin: function (cb) { const _this = this ; wx.login({ success: function (res) { //获取code然后去访问服务端登录接口,code主要是为了换openId和session_key。 if (res.code) { wx.request({ url: _this.domain + _this.api.loginCheckReq, method: 'POST' , header: { 'Content-Type' : _this.globalData.postHeader }, data: { jsCode: res.code, }, success: function (res) { //登录成功 if (res.data.result == 1) { wx.getUserInfo({ withCredentials: true , success: function (result) { res.data.wechatUserInfo = result.userInfo; _this.globalData.userInfo = res.data; _this.globalData.userInfo.face = '/uploadFiles/' + res.data.userFace; typeof cb == "function" && cb(_this.globalData.userInfo) wx.setStorageSync( 'userInfo' , _this.globalData.userInfo); //将用户数据存入内存 }, fail: function () { _this.globalData.userInfo = res.data; _this.globalData.userInfo.face = res.data.prefix + '/uploadFiles/' + res.data.userFace; typeof cb == "function" && cb(_this.globalData.userInfo) wx.setStorageSync( 'userInfo' , _this.globalData.userInfo); } }) } } }) } } }) },
首先小程序端访问wx.login()接口获取code,然后调用服务端的登录代码。服务端的登录伪代码如下:
public String xcxLogin(){ Integer result; Map<String,Object>map= new HashMap<String, Object>(); try { HttpServletRequest req = ServletActionContext.getRequest(); String jsCode = req.getParameter( "jsCode" ); String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + ConfigUtil.XCX_APP_ID + "&secret=" + ConfigUtil.XCX_APP_SECRET + "&js_code=" + jsCode + "&grant_type=authorization_code" ; String urlDetail = URLConnectionUtil.getUrlDetail(url); //访问小程序接口,获取openId,session_key JSONObject jsonObject = JSONObject.fromObject(urlDetail); String openId=jsonObject.getString( "openid" ); String session_key=jsonObject.getString( "session_key" ); TUser user=getUserByOpenId(openId); if (user== null ){ //新增用户,插入到数据库 TUser userTmp= new TUser(); user.setOpenId(openId); addUser(userTmp); user=userTmp; } session.put( "user" , user); //将user信息放入session session.put( "session_key" , session_key); //将session_key放入session map.put( "user" , user); //将user信息响应给小程序端 map.put( "SESSION" , req.getSession().getId()); //将sessionId响应给小程序端 result= 1 ; //登录操作成功的标志位 } catch (Exception e) { e.printStackTrace(); } map.put( "result" , result); JSONObject resInfo=JsonUtil.mapToJsonObject(map); OutPutMsg.outPutMsg(resInfo.toString()); //将数据响应给小程序端 return null ; }
