声明:本文为作者原创文章,转载请注明出处 https://www.cnblogs.com/MaMaNongNong/p/9127416.html 

原理知识准备

   对于已经熟悉了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"] = ; 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

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

  1. 如何解决微信小程序界面适配问题-引用-生命周期回调函数-优化机制-样式引入

    如何解决微信小程序界面适配问题 .wxss page{ height: 100%; width:750rpx; } this.setData({ imageWidth: wx.getSystemInf ...

  2. 解决微信小程序使用wxcharts在屏幕不固定问题-开发工具里也显示好了布局,为啥到真机就是乱的

    解决微信小程序使用wxcharts在屏幕不固定问题-开发工具里也显示好了布局,为啥到真机就是乱的 .chart{ width: 100%; text-align: center; } .canvas{ ...

  3. 解决微信小程序登录与发布的一些问题

    解决微信小程序的问题 图片在电脑上显示但在手机上却无法显示的问题 要使用的是本地图片,不想把图片上传到网络再通过https的方式解决,解决方法如下: 1.image src中的图片地址对英文字母大小写 ...

  4. 解决微信小程序用 SpringMVC 处理http post时请求报415错误

    解决微信小程序用 SpringMVC 处理http post时请求返回415错误 写微信小程序时遇到的问题,这个坑硬是让我整了半天 wx.request请求跟ajax类似处理方法一致 小程序端请求代码 ...

  5. 一招解决微信小程序中的H5缓存问题

    一招解决微信小程序中的H5缓存问题1.问题描述开发过程中,为了更新代码方便,往往会在小程序中嵌入H5页面.但问题来了,小程序原生代码更新版本后,简单的从微信中删除或者代码强刷就可以解决缓存问题,但小程 ...

  6. (十二)微信小程序实现登陆页面+登陆逻辑

    微信小程序实现登陆页面 实现上面两个页面 第一个页面 <view> <!-- 上侧部分 --> <view class="top-view"> ...

  7. 解决微信小程序的wx-charts插件tab切换时的显示会出现位置移动问题-tab切换时,图表显示错乱-实现滑动tab

    解决Echarts在微信小程序tab切换时的显示会出现位置移动问题 tab切换时,图表显示错乱 <canvas class="kcanvas" canvas-id=" ...

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

    拿到一个微信小程序的项目,需要配置https安全链接(为什么必须使用https不再赘述),预想这个已经很成熟的流程,应该不会有太大问题,结果还真是出乎意料,竟然掉进一个大坑,折腾好久. 申请证书配置的 ...

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

    Windows10笔记本上运行微信小程序开发者工具,输入框(input,textarea)没有焦点,只能在真机调试,效率太低.后来发现是Window10对笔记本高分屏支持不好,要DPI缩放,导致兼容性 ...

随机推荐

  1. linux sort排序命令的高级用法(按多个列值进行排列)

    http://www.jquerycn.cn/a_9076 在linux中,使用sort按行进行排序是很简单的.不过有时,生活总是爱抛给你一个一个的问题.如果使用sort按多个列值排列,同时使用tab ...

  2. python的文件读写笔记

    读写文件是最常见的IO操作.Python内置了读写文件的函数,用法和C是兼容的. 读写文件前,我们先必须了解一下,在磁盘上读写文件的功能都是由操作系统提供的,现代操作系统不允许普通的程序直接操作磁盘, ...

  3. 【翻译】Flume 1.8.0 User Guide(用户指南)

    翻译自官网flume1.8用户指南,原文地址:Flume 1.8.0 User Guide 篇幅限制,分为以下5篇: [翻译]Flume 1.8.0 User Guide(用户指南) [翻译]Flum ...

  4. 2019.03.09 codeforces833B. The Bakery(线段树优化dp)

    传送门 线段树优化dpdpdp入门题. 要求把nnn个数分成kkk段,每段价值为里面不相同的数的个数,求所有段的价值之和最大值.n≤35000,k≤50n\le35000,k\le50n≤35000, ...

  5. C#在SharePoint文档库下动态新增文件夹

    /// <summary> /// 在创建SP文库库下动态新增文件夹 /// </summary> /// <param name="spList"& ...

  6. SQL Server数据库设置自动备份策略

    一. 简单介绍 SQL Server自带的维护计划是一个非常有用的维护工具,能够完成大部分的数据库的维护任务. 数据库的备份也是日常工作中非常重要的一个环节.备份的方法非常的多. 今天给大家介绍最简单 ...

  7. linux系统中使用socket直接发送ARP数据

    这个重点是如这样创建socket:  sock_send = socket ( PF_PACKET , SOCK_PACKET , htons ( ETH_P_ARP) ) ; 其后所有收发的数据都是 ...

  8. IT行业三大定律

    1:摩尔定律 该定律由Inter公司创始人戈登摩尔提出,摩尔定律指出:每一年半计算机等IT产品的性能会翻一番:或者说相同性能的产品在一年半后价格会降一半.   表现为:为适应摩尔定律,IT公司必须在较 ...

  9. Spring-AspectJ 配置文件

    <?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.spr ...

  10. thinkphp添加数据 add()方法

    thinkphpz内置的add()方法用于向数据库表添加数据,相当于SQL中的INSERT INTO 行为添加数据 add 方法是 CURD(Create,Update,Read,Delete / 创 ...