小程序会话session

在小程序, 根据实践和资料 确定一个事实: 小程序没有Session机制, 但小程序可通过'标识'来实现登陆状态

在微信小程序中,我们可能涉及到以下三类登录方式:

  • 自有的账号注册和登录
  • 使用其他第三方平台账号登录
  • 使用微信账号登录(即直接使用当前已登录的微信账号来作为小程序的用户进行登录)

先做一个测试, 获取SessionID:

@Controller
public class GetSessionTestController {
	@RequestMapping("/getSession")
	public void getSessionTest(HttpServletRequest request) {
		HttpSession session = request.getSession();
		System.out.println(session.getId());
	}
}

使用小程序多次发如下请求, 得到SessionID都不相同 

wx.request({
    url: 'http://localhost:4444/getSession',
})

使用浏览器多次发如下请求, 得到的SessionID是相同

 http://localhost:4444/getSession

原理是这样的: 使用浏览器发请求, SessionID会来回传递, 使用的是同一个Session, 所以SessionID相同

而使用小程序发请求, 就不一样了, 小程序开发者服务器之间还有微信服务器

所以它不是单纯地小程序与开发者服务器之间来回传递, 因此小程序与开发者服务器之间的SessionID动态变化的

如下是第三种方式(使用微信账号)登陆流程:

1.获取临时登陆凭证

小程序使用开放接口: wx.login() 先获取用户临时登陆凭证code

临时登陆凭证是一个用户进入小程序时, 小程序分配给用户的一个"号码牌" (以下称为号码牌)

这个号码牌, 只能使用一次, 使用后就过期

//app.js
App({
  onLaunch: function () {
    // 登录
    wx.login({
      success: res => {
        console.log("res.code : " + res.code);
        // 下一步: 发送 res.code 到后台换取 openId, sessionKey, unionId    
      }
    })
)}

我把这个值打印出来: 033uxPHm0nXOgk1WjcEm0uiDHm0uxPHX

当另一个用户进入该小程序时, 这个号码牌显然是不一样的

2.发起网络请求

当小程序获取到这个号码牌, 则需要向开发者服务器发起请求

 wx.login({
   success: res => {
     if (res.code) {
        //发起网络请求
        wx.request({
          url: 'https://xxx/xxx',        // 开发者服务器的登陆url
          data: {
            code: res.code               // 发送的数据是号码牌
          }
        })
     } else {
       console.log('登录失败!' + res.errMsg)
     }
  }
})

3.换取session_key 和 openid

当开发者服务器获取到了号码牌, 需要对其进行校验, 地址:

这个请求地址是在开发者服务器中发送

https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code

请求的数据:

参数: appid 必填 小程序唯一标识
参数: secret 必填 小程序的 app secret
参数: js_code 必填 登录时获取的 code
参数:grant_type 必填 填写为 authorization_code

校验成功时返回的json, 包括session_key和openid, 还可能包含UnionID

失败时返回的json, 包括errorcode和errmsg

session_key是会话密钥(开发者服务器应该对其保密)

openid是用户唯一的标识(标识的是一个微信号)

UnionID是用户在开放平台的唯一标识符(只有在满足UnionID的下发条件才能获取到)

{                                        //正常返回的JSON数据包
   "openid": "OPENID",
   "session_key": "SESSIONKEY",
}
{                                        //满足UnionID返回条件时,返回的JSON数据包
   "openid": "OPENID",
   "session_key": "SESSIONKEY",
   "unionid": "UNIONID"
}
{                                        //错误时返回JSON数据包(示例为Code无效)
   "errcode": 40029,
   "errmsg": "invalid code"
}

4.生成一个会话标识

得到openid和session_key后, 还需要根据openid生成一个"会话标识" - session_token, 返回给小程序

可以这么做:

        为用户生成一个唯一的字符串作为键,可以将session_key和openid作为值,存入redis中,并设置超时时间

5. 在处理需要登陆的业务时, 小程序发起的请求需要带上session_token,后端校验:

.储存session_token:

success: res => {
    wx.setStorageSync("session_token", res.header.session_token);
}

.获取session_token: 

var s = wx.getStorageSync("session_token");

.在时候带上session_token(可以放在header中传递):

click : function() {
    var session_token = wx.getStorageSync("session_token");
    wx.request({
      url: 'http://127.0.0.1:4040/get3rdSession',
      header: {
        "session_token" : session_token
      }
    })
 }

.开发者服务器中校验:

@RequestMapping("/isLogin")
public Object isLogin(HttpServletRequest request) throws Exception {
    // 从header中取出session_token	
    String session_token = request.getHeader("session_token");
    // 校验等操作, 如果没有登陆, 则..., 如果登陆了则...
}
	

// 有所执着

猜你喜欢

转载自blog.csdn.net/lljxk2008/article/details/82286031
今日推荐