微信小程序模拟饼干的实现

  


  

  

现有系统已经有一套完整的接口,用户状态,验证都是基于饼干的。

  

部分业务要上小程序版本,众所周知,微信小程序不支持饼干的。要上线的业务,最好的方式还是基于现有这套接口做,改动不大,也最快。

  


  

  

通过浏览器的开发工具,网络栏查看请求,浏览器中的cookie会携带在每个http的请求头里面,用饼干作为键名。

  

那么,在微信官方请求方式wx。请求中,我们设置头,添加一个饼干应该可以得以模拟。

  

问题又来了,怎么获取到服务器返回的饼干呢。

  

通过登录接口(登录的时候,服务器端会植入饼作为会话),查看http返回头。

        wx.request ({   url:/api/登录,   成功:(数据)=比;{   如果(数据)。statusCode===200) {   console.log(数据);//数据中应该会有set - cookie或set - cookie的字样,嗯,那就是服务器种下的饼干   }   }   })   之前      

拿到饼干存入本地中,下次请求数据的时候直接塞进去,完美。

  


  

  

原本以为饼干只需要一进一出就可以完美模拟,实际操作才发现,携带上去的饼干服务器无法识别。

  

服务器返回的饼干中,会携带上很多储存用的字段,例如路径=/;

     //服务器放回的饼干   让饼干=' userKey=1234567890;同名路径=/;到期=星期四,2018年6月21日13:15:08格林尼治时间;HttpOnly,用户id=111;路径=/;日格林尼治时间到期=星期四,2018年6月21日13:15:08昵称=;路径=/;日格林尼治时间到期=星期四,2018年6月21日13:15:08用户名=111111;路径=/;日格林尼治时间到期=星期四,2018年6月21日13:15:08 imgUrl=;路径=/;到期=星期四,2018年6月21日格林尼治时间13:15:08 ';//模拟的是需要的格式样式   让virtualCookie=' userKey=1234567890;同名用户名=111111;用户id=111;”;   之前      

妈耶~要怎么过滤呢。

  

简单粗糙的写了一个过滤方案。

     //cookie的本地存储位置   const COOKIE_KEY=癬_cookie_key__”;/* *   *格式化用户需要的饼干   */const normalizeUserCookie=(饼干=")=比;{   让__cookies=[];   (cookies.match (/((\ w \] *)=([^ \ s=] +);/g) | | []) .forEach ((str)=比;{   如果(str !===/;路径的,,str.indexOf (csrfToken=) !==0) {   __cookies.push (str);   }   });   wx。setStorageSync (COOKIE_KEY __cookies。加入(' '));   };      之前      

<代码> csrfToken> 鸡蛋。js> =/;路径> =/;路径

  

<代码> normalizeUserCookie 主要是过滤了<代码> xx=xxx> =/;路径这样无意义的数据。

  

在登录接口的时候,存上饼干,在接下来的请求中带上,那么,应该,没错,可能,可以模拟了。

  


  

  

鸡蛋内置的<代码> egg-security>   鸡蛋。js虽然可以在配置中关闭CSRF,但是,如果一定要使用呢?

  

首先,要弄明白一件事,<代码> csrfToken 怎么来的。

  

经过多次验证得知,当http请求时,在约定位置没有携带上csrfToken值,此次请求会在返回的cookie中携带上一个新的csrfToken;当本次请求已携带上值,就不会产生成csrfToken。当约定位置带上的csrfToken与饼干里面的csrfToken一致时,通过验证。

  

接上面的<代码>格式化用户需要的饼干操作,先抛开csrfToken单独处理用户状态等。

  

在每次请求结束后,试着单独拿饼干中可能存在的csrfToken,有值就缓存,没值跳过用旧值。

  


  

  

本次小程序是基于wepy的,所以使用了优化后的<代码> wepy.request>   

基于鸡蛋。js的版本。

  

可能与实际开发有点出入,适当修改。

        从“进口wepy wepy ';      出口const HTTP_HOST=' http://127.0.0.1:3000 ';      出口const HTTP_HOST_API=' $ {HTTP_HOST}/api/wxmp”;//cookie的本地存储位置   const COOKIE_KEY=癬_cookie_key__”;//csrfToken的本地存储位置   const CSRF_TOKEN_KEY=癬_csrf_token__”;/* *   *清除用户饼干   */出口const cleanUserCookie=()=比;{   wx。setStorageSync (COOKIE_KEY”);   }/* *   *格式化用户需要的饼干   * @param{字符串}饼干   */出口const normalizeUserCookie=(饼干=")=比;{   让__cookies=[];   (cookies.match (/((\ w \] *)=([^ \ s=] +);/g) | | []) .forEach ((str)=比;{   如果(str !===/;路径的,,str.indexOf (csrfToken=) !==0) {   __cookies.push (str);   }   });   wx。setStorageSync (COOKIE_KEY __cookies);   };/* *   *格式化令牌   */const normalizeCsrfToken=()=比;{   让__value=https://www.yisu.com/zixun/wx.getStorageSync (CSRF_TOKEN_KEY) | |”;   让__inputs=__value.match (/csrfToken=[\ S] */) | | [];   让__key=__inputs [0];//csrfToken=1212132323;   如果(! ! ! __key) {   返回”;   }//脱水   返回__key.replace(/,/美元”)。替换(/^ csrfToken=/?;   };/* *   *保存csrf的饼干   *不一定每次请求都会更新饼干   * @param{字符串}饼干   */const seveCsrfTokenCookie=(饼干)=比;{   如果(饼干){   wx。setStorageSync (CSRF_TOKEN_KEY、饼干);   }   };/* *   *请求数据   * @param}{对象选择   */出口const doAjax=(选择)=比;{   返回新的承诺((解决,拒绝)=比;{   让饼干=wx.getStorageSync (COOKIE_KEY) | | [];   让csrf=normalizeCsrfToken ();   让url=opt.url;//整理饼干   Cookies.push (“csrfToken=$ {csrf};”);//设置请求头部   opt.header=Object.assign (   {   “x-csrf-token”:攻击,   饼干:饼干。加入(' ')   },   opt.header | | {}   );   opt.success=(数据)=比;{   seveCsrfTokenCookie (data.header [' set - cookie ']);//统一操作   如果(数据)。statusCode==200) {   如果(url===/登录){   normalizeUserCookie (data.header [' set - cookie ']);   }   解决(data.data);   其他}{   拒绝(“未知错误,请重试一次”);   }   };   opt.fail=(err)=比;{   拒绝(错);   };   opt.url=" $ {HTTP_HOST_API} $ {opt.url} ';   wepy.request(选择);   });   };      

微信小程序模拟饼干的实现