微信小程序和具有权限认证、CSRF机制的Django服务端交流

本教程基于Django后端,在cookies的命名和csrftoken的接收上可能和其他语言框架的有所不同。

首先要知道一些基本知识:当微信小程序在会话时间内想要再次向服务端请求时,不需要再次登录,只需要把sessionid放进cookie中传递过去就可以了,为了防止跨域请求,还要携带上csrftoken。微信小程序不像浏览器那样在二次请求时会自动携带cookiescookies需要我们自己写上。

总体交流过程

1、微信小程序使用wx.login()获取到code后发送给服务端

2、服务端向微信服务器请求得到openidsession_key,后端处理注册登录后,通过session记录用户登录状态,最后返回给微信小程序的cookiescsrftokensessionid

3、微信小程序二次请求时在请求头部携带cookiecookie中存放上次请求得到的csrftokensessionid,并且请求头部中还要有一个X-CSRFToken键值对。

关键部分的详细操作

第一步:微信小程序本地缓存 csrftoken 和 sessionid

首先在第一次登录请求时就要把csrftokensessionid获取下来,并分别保存在缓存中。(为什么要分别保存?因为等下二次请求时要分别用到)

wx.login({
  success: res => {
    if (res.code) {
      wx.request({
        url: xxx,
        method: 'POST',
        data: { 'code': res.code },
        success: res => {
          if (res.statusCode == 200) { //服务端处理正常,登录成功
            //wx.setStorageSync("cookies", res.header["Set-Cookie"]); //存进去的是所有cookie串在一起的字符串,包括csrftoken和sessionid,但我们不要用这个方式,原因见下文介绍
            wx.setStorageSync('csrftoken', res.cookies[0])
            wx.setStorageSync('sessionid', res.cookies[1])
          }
        },
      });
    }
  }
});

在上面你看到了,我在保存csrftokensessionid到缓存时,使用的是res.cookies,而不是res.header["Set-Cookie"],本来微信小程序接收到的cookies就是和 res.header["Set-Cookie"] 一样的,但在二次提交时这个东西并没有想象中那样可以直接使用。。

第二步:微信小程序二次请求时携带 cookie 和 X-CSRFToken

本地缓存中已经有csrftokensessionid了,二次请求时要先处理得出这两样东西:

1、csrftokensessionid合并后的cookie

2、纯粹的、没有cookie信息的csrftoken

其实第一项中的cookie本来是可以直接用res.header["Set-Cookie"]这个得到的cookies字符串就可以了的,但不知道为什么,这个字符串中的csrftokensessionid这两个cookie并不是用分号;和空格隔开的,而是用一个逗号,隔开,这个cookie发送到后端是识别不出来的。。

所以需要这样设计:

let cookie = wx.getStorageSync("csrftoken") + '; ' + wx.getStorageSync("sessionid")

而纯粹的、没有cookie信息的csrftoken又是怎么回事?

用过ajaxDjango服务端发送请求的人都知道,在headers中是要填写X-CSRFToken键值对的,而在Django的模板语言中,我们往往可以直接用X-CSRFToken:'{{ csrftoken }}' 这样的简单方式来生成纯粹的csrftoken,但微信小程序可没有这个模板语言,而在我们保存的cookie中的那个csrftoken是携带着其他信息的,所以要我们去截取出纯粹的csrftoken

截取方式:

csrftoken = wx.getStorageSync("csrftoken").split(';')[0].split('=')[1]

对这个截取方式不理解的可以展开wx.getStorageSync("csrftoken")看一下就明白了,其实就是对这个字符串先按分号分割然后取第一个元素再按等号分割后取第二个元素,也就是纯粹的csrftoken

所以我们在二次请求时,应该这样:

wx.request({
  url: xxx,
  data: "",
  method: 'POST',
  header: {
    'cookie': wx.getStorageSync("csrftoken") + '; ' + wx.getStorageSync("sessionid"),
    'X-CSRFToken': wx.getStorageSync("csrftoken").split(';')[0].split('=')[1]
  }
})

至此,我们就实现了微信小程序携带cookiecsrftoken向Django服务端请求的需求。

注意:微信小程序wx.requestcookie是单数,header也是单数。

我开了个微信公众号,经常在上面发一些个人思考和计算机技术、技巧的文章,欢迎来关注一下哈:
微信小程序和具有权限认证、CSRF机制的Django服务端交流_第1张图片

你可能感兴趣的:(Django)