我在這裡詳細表述一遍:微信小程式和具有權限認證、CSRF機制的Django服務端通信的一個可行的例子。。
本教程基于預設,在
Django
的命名和
cookies
csrftoken
的接收上可能和其他語言架構的有所不同。
首先要知道一些基本知識:當微信小程式在會話期間想要再次向服務端請求時,不需要再次登入,隻需要把sessionid放進cookie中傳遞過去就可以了,以便防止跨域請求,還要攜帶上csrftoken。微信小程式不像浏覽器那樣在二次請求時會自動搬運
,
cookies
需要我們自己寫上。
cookies
總體交流過程
1,微信小程式使用
wx.login()
擷取到
code
後發送給服務端
2,服務端向微信伺服器請求得到
openid
和
session_key
,進行處理注冊登入後,通過
session
記錄使用者登入狀态,最後傳回給微信小程式的
cookies
有
csrftoken
和
sessionid
3,微信小程式二次請求時在請求上方移動
cookie
,
cookie
中存放上次請求得到的
csrftoken
和
sessionid
,并且請求頭部中還要有一個
X-CSRFToken
鍵值對。
關鍵部分的詳細操作
第一步:微信小程式本地緩存csrftoken和sessionid
首先在第一次登入請求時就要把
csrftoken
和
sessionid
擷取下來,并分别儲存在緩存中。(為什麼要分别儲存?因為等下二次請求時要分别用到)
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])
}
},
});
}
}
});
複制
在上面你看到了,我在儲存
csrftoken
和
sessionid
到緩存時,使用的是
res.cookies
,而不是
res.header["Set-Cookie"]
,本來微信小程式接收到的
cookies
就是和
res.header["Set-Cookie"]
一樣的,但在二次送出時這個東西并沒有想象中那樣可以直接使用。。
第二步:微信小程式二次請求時攜帶cookie和X-CSRFToken
本地緩存中已經有
csrftoken
和
sessionid
了,二次請求時要先處理後續兩種樣東西:
1,
csrftoken
和
sessionid
合并後的
cookie
2,純的,沒有
cookie
資訊的
csrftoken
其實第一項中的
cookie
本來是可以直接用
res.header["Set-Cookie"]
這個得到的
cookies
字元串就可以了的,但不知道為什麼,這個串聯中的
csrftoken
和
sessionid
這兩個
cookie
并非用分号
;
和間隔替換的,否則用一個逗号
,
隔開,這個
cookie
發送到後端的英文識别不出來的..
是以需要這樣設計:
let cookie = wx.getStorageSync("csrftoken") + '; ' + wx.getStorageSync("sessionid")
複制
而純粹的,沒有
cookie
資訊的
csrftoken
又是怎麼回事?
用過
ajax
向
Django
服務端發送請求的人都知道,在
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]
}
})
複制
至此,我們就實作了微信小程式攜帶
cookie
和
csrftoken
向Django服務端請求的需求。
注意:微信小程式的
wx.request
是單數,也是
cookie
單數。
header