从session原理出发解决微信小程序的登陆问题

原理知识准备

   对于已经熟悉了session原理的同学来说,我们都清楚:在浏览器端我们会存储一个sessionId,用它来作为凭证,在服务器端得到有关本次浏览器与服务器会话的所有信息,这些信息是储存在服务器端的存储空间中的,它完全可以用来判断一个浏览器端的登录状态,因为它是由服务器端来掌控的,是安全的。

  那么浏览器端是用什么来存储这个sessionId? 并且浏览器又是如何将sessionId传回给服务器的呢?

  大体上是有两种方法的:

    1、使用浏览器端实现的cookie功能,每次浏览器都会将服务器传过来的cookie内容按键值对的方式放到浏览器的缓存中,然后下次请求同一个服务器时又会将cookie内容取出来送回服务器,当然其中就有存储在cookie中的sessionId。

    2、使用URL重写的方法,URL地址重写是对客户端不支持Cookie的解决方案。URL地址重写的原理是将该用户Session的id信息重写 到URL地址中。服务器能够解析重写后的URL获取Session的id。这样即使客户端不支持Cookie,也可以使用Session来记录用户状态。

  配上一张自己画的丑图:

    

  不到迫不得已的地步,我是不会考虑第二种,也就是使用URL重写的方法的。

  其实,实际的应用场景无非就是以下两种,我们用病人看病的例子来理一理:

  第一种,医生给病人看病,一天有几百个病人,不可能把所有的病人的病情都记得清清楚楚,所以就需要一个病历本,病人下次来看病的时候医生就可以根据病人的病历本上记录的信息来得到病人的病情状况。(这种情况对应的就是浏览器端只使用cookie与服务器进行交互的情况)

  第二种,有一些特殊的病人,他们是毒瘾患者,正在接受戒毒的辅助治疗,每个月需要到医院领取少量的类似毒品的药物来逐步减少毒品摄入量;医院也给他一个病历本,但是由于使用药物的特殊性,为了防止某些不法分子伪造病历本去领取违禁药物,于是就给每个病历本上使用GUID算法生成了一个独一无二的病历号,在医生这里也有一个本子,上面记录了所有特殊病人的病历号,下次病人来拿违禁药物的时候,医生需要对照病人的病历号来查询是否存在这个病人和他需要领取药品的具体量。这样,就可以防止非法人员冒充和病人恶意更改药品领取量的情况发生。(这种情况对应的就是通过sessionId来查询出本次浏览器与服务器的会话信息的情况,病历本上的病历号就相当于sessionId)

  上面写了这么多关于session的原理内容就是为了下面引出正题做准备的,所以到这里还不明白session原理的同学可以绕道去找一些关于session的文章研究研究,再回来接着往下看。

  推荐一篇大神的关于session原理的文章:

  https://www.cnblogs.com/linguoguo/p/5106618.html

问题提出

  下面展开正题,问题是这样的:

  在开发微信小程序的过程中需要实现一个小程序登陆的功能,由于小程序中与服务器的交互大部分使用的都是HTTP通信,所以完全可以仿照之前开发B/S的那一套登陆体系,利用上面提到的sessionId的方式在服务器端进行登陆态的存储,进行是否登录的判断。相对于以前的 服务器/浏览器 的开发模式,服务器/微信小程序 的开发模式有一个初级开发者需要注意的点,就是:微信小程序是不会将HTTP报文头中的COOKIE信息存入缓存中的,自然也就不会将COOKIE的内容传回给服务器端,简单的说就是 微信小程序端没有帮你实现cookie机制

  

  所以,如果你想当然的就认为微信小程序已经帮你在背后实现了cookie机制,那么你就会像我一样,踩入了一个大坑。

  下面是我的踩坑历程,咱从坑中领悟:

  

服务器端的一段程序(.net MVC 的 Action方法程序)

  

        public ActionResult SessionTest()
        {
            Session["TestValue"] = 1;

            return Json(new { message = "this is a test response" });
        }    

  

使用微信小程序的原生request方法写的请求程序

 sendRequest:function(){

    wx.request({

        url:‘http://localhost:51112/Test/SessionTest‘,
        method:‘POST‘,
        success:function(res){

          console.log("进行了一次请求");

        },
        fail:function(){

          console.log("请求失败");

        }
    });

  }

  过程就是用小程序的这段代码运行,去请求服务器,服务器执行的就是上面展示的那段action方法的代码。

   总共请求两次,两次请求的http报文头如下:

  第一次请求:

  

  (请求报文头):

   

  (应答报文头):

 

  由于这是微信小程序第一次与服务器进行交互,所以并没有携带任何cookie的内容,这是很正常的现象。等到服务器应答浏览器时,就给了浏览器一个sessionId,字段名为 ASP.NET_SessionId  值为  saqu0pv20q5jkd1q2dlmxcyg 。到这里我们如果认为微信小程序已经实现了cookie机制,那么下一次向同一个域名进行请求的时候,我们会在请求报文头中看到会有一个cookie字段,里面会有上一次微信小程序从服务器那里得到的sessionId的值。

  然而。。。

  

 第二次请求:

 

  

(请求报文头):

   

  (应答报文头):

    

  看到这里你就会发现它与你预想的完全不一样了。。首先,请求报文头中并没有发现有上一次服务器给微信小程序端传的sessionId;然后,服务器返回给小程序的报文头中的 ASP.NET_SessionId  值变成了 cwugbbt0mmliha0ul4ccx4l2  并非原先的  saqu0pv20q5jkd1q2dlmxcyg 。

   发生的一切都指向一个原因,那就是 小程序并没有实现cookie的机制,导致小程序请求服务器的报文头中并没有携带sessionId,服务器拿不到sessionId,就会认为这是另外一个还没有对服务器请求过的客户端,就新生成了一个sessionId给微信小程序端,所以小程序端就拿到了不同于上次的sessionId。

   到现在,所有的现象以及现象背后的原因都解释通了,那么接下来就是怎么解决问题。

解决方法与过程

      其实解决问题的方法很简单,既然微信小程序端没有实现cookie机制,那么就自己实现cookie机制呗。

   思路:cookie机制最简单的功能无非就是将服务器返回的 应答报文中cookie部分找个地方存起来,以后再向服务器发出请求时就将存储的cookie内容取出,填充到请求报文头中。

   存到一个地方,存到哪呢?有两个合适的地方:

    1、微信小程序的缓存。

      2、微信小程序的全局变量中。

   我选择第二种,将cookie内容存到微信小程序的全局变量中去,下面是我自己封装的一个自动携带cookie中的sessionId去请求的请求函数实现:

   在封装之前,最好先去微信小程序的官网看一下   wx.request 函数的说明。点这里

//app.js
App({

  globalData: {
    cookie: ‘‘,      //供小程序存储cookie数据使用
  }
})

//带着sessionId进行请求,自动获取服务端返回的sessionId存入全局变量中
function RequestBySessionId(requestParam){

  //三个默认参数的值
  var method = "GET";
  var dataType = "json";
  var responseType = "text";
  //用户输入了参数就替换,没输入就使用默认的
  if ("method" in requestParam)
  {
    method = requestParam.method;
  }
  if ("dataType" in requestParam) {
    dataType = requestParam.dataType;
  }
  if ("responseType" in requestParam) {
    responseType = requestParam.responseType;
  }

  var url = requestParam.url;
  var data = requestParam.data;
  var success = requestParam.success;
  var fail = requestParam.fail;
  var complete = requestParam.complete;

  var cookieStr = "";  //请求报文头中cookie的字符串

  var Cookie = App.globalData.cookie;  //获取全局变量中的cookie内容
  cookieStr = Cookie;

  var header = {};
  if ("header" in requestParam)
  {
    header = requestParam.header;
    header["Cookie"] = cookieStr;
  }
  else
  {
    header["Cookie"] = cookieStr;
  }

  wx.request({
    url: url,
    method: method,
    responseType: responseType,
    dataType: dataType,
    data: data,
    header: header,    //每次请求带上sessionId
    success: function(res){

      //先将检查服务器返回报文头中有无sessionId,有则存到全局变量中
      var cookie = res.header["Set-Cookie"];
      if (undefined != cookie)
      {
        var sessionPos;
        if ((sessionPos = cookie.indexOf("ASP.NET_SessionId=")) != -1) {

          //每次请求成功都将sessionId存入全局变量
          App.globalData.cookie = cookie.substring(sessionPos, 42);
        }
      }
      //执行正常的操作
      success(res);
    },
    fail: fail,
    complete: complete,
  });
}

  经过了这一波封装,就等于是有了微信小程序中请求的”神器“了,麻麻再也不用担心我把sessionId搞丢了。

  

  下面咱就再一次使用封装后的函数来进行请求发送试验:

  

   改造后的微信小程序端请求代码:

  var utils = require(‘../../utils/util.js‘); //引用 util.js 文件

  sendRequest:function(){

    utils.RequestBySessionId({

      url: ‘http://localhost:51112/Test/SessionTest‘,
      method: ‘POST‘,
      success: function (res) {

        console.log("进行了一次请求");

      },
      fail: function () {

        console.log("请求失败");

      }
    });

  }

  

   同样的过程:用小程序的这段代码运行,去请求服务器,服务器执行的就是上面原先展示的那段action方法的代码。

   总共请求两次,两次请求的http报文头如下:

  第一次请求:

  

  (请求报文头):

   

  (应答报文头):

 

  看到这次服务器返回的 ASP.NET_SessionId  值为  dodngz2ahcznp4r3hrmavd1c。

  然后,注意了。。。

  

 第二次请求:

 

  

(请求报文头):

   

  看到第二次请求报文头中的cookie了吗,里面就是 ASP.NET_SessionId= dodngz2ahcznp4r3hrmavd1c,

   说明了,已经成功将sessionId带上了。。。

  (应答报文头):

    

  服务器返回的报文中已经没有sessionId了,因为已经不需要了。。。

  

    以上就是我对微信小程序中自创cookie的解决方法,其实你会发现原理其实很简单,但是如果你没有深入过session的原理,你会很迷惑。

  所以,还是那句话:明白原理最重要,掌握了原理也就掌握了一切。。。

  晚安,同学们。

  

  

原文地址:https://www.cnblogs.com/MaMaNongNong/p/9127416.html

时间: 2024-08-07 16:13:30

从session原理出发解决微信小程序的登陆问题的相关文章

使用CryptoJS解决微信小程序用户信息解密

使用CryptoJS解决微信小程序用户信息解密 问题描述: wx.getUserInfo(OBJECT)微信官方的这个获取用户信息的方法,需要对接口返回的加密数据( encryptedData )进行对称解密. 微信官方有提供加密数据解密算法 接口如果涉及敏感数据(如wx.getUserInfo当中的 openId 和unionId ),接口的明文内容将不包含这些敏感数据.开发者如需要获取敏感数据,需要对接口返回的加密数据( encryptedData )进行对称解密. 解密算法如下: 对称解密

解决微信小程序开发者工具输入框焦点问题

Windows10笔记本上运行微信小程序开发者工具,输入框(input,textarea)没有焦点,只能在真机调试,效率太低.后来发现是Window10对笔记本高分屏支持不好,要DPI缩放,导致兼容性问题.解决方法: 显示设置.缩放与布局改为100%.这样就可以点击输入框了,但是字体变得很小,最好是外接显示器. 不修改DPI缩放,长按输入框即可! 原文地址:https://www.cnblogs.com/ycwu314/p/11258489.html

解决微信小程序配置https不成功问题

拿到一个微信小程序的项目,需要配置https安全链接(为什么必须使用https不再赘述),预想这个已经很成熟的流程,应该不会有太大问题,结果还真是出乎意料,竟然掉进一个大坑,折腾好久. 申请证书配置的详细流程不再写了,大概就是去腾讯云或者阿里云申请一个ssl证书,按照自己的网站架构下载相应的证书,导入到自己的服务器,导入方法下载时有详细教程. 这里需要注意几点: 1. htpps默认使用443端口,请确认443未被占用 2.在防火墙中添加新的入站规则,允许443端口被访问.(我用的阿里云服务器E

解决微信小程序开发中wxss中不能用本地图片

微信小程序开发中wxss中不能用本地图片,我们可以用将我们的图片传到服务器上,然后直接引用在线地址.但是当我们没有服务器时,我们可以用"图床",这个具体可以百度.这里我们用第二种方法:将图片用base64加密. 1.我们用在线加密对图片进行加密,这个网址百度一大堆,我只贴出一个http://imgbase64.duoshitong.com/ 2.将转换完成后的base64复制到我们要引用的地方. 3.设置样式(辅助代码,只有将这个图片做为background-image时注意设置如下属

解决微信小程序手机请求数据不返回的问题

在微信开发者工具开发好小程序之后想要在手机上预览调试,发现手机上请求不到数据,在微信开发者工具上就能返回数据. 这是个大坑. 解决方法: 首先要安装最新的微信开发者工具,最新的才有远程调试功能 以为这样就可以了? 还有个坑,我是在本地用node开发的接口,本地开发时候是这样调用的 这样在微信开发者工具中是没问题的,是有数据返回的.但是在手机上就不行了,没数据返回. 经过多次试验,发现要用IP地址请求才行 - -!!!!!!!!!!(要注意下:不能用127.0.0.1,要用本机的IP地址,cmd打

17行代码解决微信小程序图片延迟加载

js 页面 Page({ data: { realScrollTop: 0,//页面滚动距离 driveHeight //屏幕高度可初始化设置 }, scroll(e){ if(e.detail.scrollTop > this.data.realScrollTop){ this.setData({ realScrollTop: e.detail.scrollTop }); } } }); wxmal页面 <scroll-view scroll-y="true" scrol

promise解决微信小程序中的request回调地狱

//使用 request(url,methods ,data).then(res => { //服务器返回数据 console.log(res ); }).catch(res => { //报错 console.log(res); }).finally(()=>{ //完成 console.log("结束"); }) //封装request方法 const request = (url, method, data) => { var promise = new

微信小程序image组件开发程序以及相关图片问题参考资料汇总

微信小程序image组件开发程序以及相关图片问题参考资料汇总,希望对大家小程序开发能有一定的参考和借鉴价值.以下汇总主要涉及到微信小程序image组件有关资源路径.缩放和剪裁模式等进行的探讨,无论是对微信小程序新手还是正在开发中的朋友都是很好的小程序学习资料. 微信小程序image组件必备基础知识: image组件默认宽度300px.高度225px image的属性mode有13种模式,其中4种是缩放模式,9种是裁剪模式 image组件开发教程汇总: 微信小程序自定义组件实现图片单指拖动.双指缩

SAP成都研究院大卫哥:SAP C4C中国本地化之微信小程序集成

今天的文章来自Wu David,SAP成都研究院C4C开发团队的架构师,在加入团队之前曾经在SAP上海研究院工作,组内同事习惯亲切地称呼他为大卫哥. 大卫哥身高据Jerry目测有1米8以上,是成都C4C开发团队身高最高的几位男同事之一.身体非常结实,是成都SAP篮球队的成员之一.有一次大卫哥坐在自己座位上,一手撑在桌子上认真地看着向他求助的同事电脑上打印的日志,飞机哥张航拍了一张大卫哥的背影,评价道:"从照片里看出了大卫哥发达的背阔肌." 飞机哥张航后来完成了一幅素描,下图左边正在沉思