django + vue3 前后端token登錄驗證
后端登錄判斷
def login(request):
if request.method == 'POST':
req = json.loads(request.body)
user_name = req['username']
password = req['password']
response = {}
user = UserInfo.objects.filter(user_name=user_name, password=password)
if user:
success(response)
print("登錄成功")
# token - session 模塊
if not request.session.session_key:
request.session.save()
print("新會話")
import hashlib
import time
request.session.set_expiry(3600 * 4)
md5 = hashlib.md5()
md5.update((user_name + password + "1258" + str(time.time())).encode())
token = md5.hexdigest()
request.session["token"] = token
response['token'] = token
request.session.save()
else:
fail(response,"用戶名或密碼錯誤")
print("登錄失敗")
res = HttpResponse(json.dumps(response))
return res
這里說明一下關鍵代碼。
用戶密碼不正確,返回錯誤即可。
當用戶密碼正確時,首先獲取request.session.session_key,如果是第一次登錄,那么改值為None。所以需要先創建該session。這里調用request.session.save()即可。
之后設置session過期時間,使用request.session.set_expiry(3600 * 4)。參數為秒。
計算token,這里使用自帶的hashlib庫隨意寫了一下,沒考慮真實情況,
# 計算token
md5 = hashlib.md5()
md5.update((user_name + password + "1258" + str(time.time())).encode())
token = md5.hexdigest()
# 設置session中的token字段值
request.session["token"] = token
# 寫入返回值,這里讓前端自行寫入cookie或localstorage
response['token'] = token
# 最后別忘保存session
request.session.save()
后端token驗證
每次調用api或者刷新界面時,可向后端發送token,驗證登錄狀態
def validToken(request):
req = json.loads(request.body)
req_token = req['token']
res = {}
# 獲取session中的token
token = request.session.get("token")
# token不存在,或者token與發送來的req_token不符合,
# 則讓客戶端重新登錄
if not token or token != req_token:
fail(res,"")
else:
success(res)
return HttpResponse(json.dumps(res))
前端登錄判斷
前端每次登錄成功后,將token寫入localstorage,這里不再列出。
這里我們看一下router前置導航守衛的寫法。
這里不采用return true/false的方法控制守衛,而采用調用next()的方法控制導航,記得保證next()方法調用且僅調用一次。此外next()參數可以傳遞要跳轉的路徑。
關於導航守衛的用法請看官方文檔https://router.vuejs.org/zh/guide/advanced/navigation-guards.html
router.beforeEach((to, from, next) => {
// 判斷是否含有token
const token = localStorage.getItem("token");
if (token) {
request({
url: "validToken",
method: "POST",
data: {
token: token,
}
})
// token 有效
.then((res) => {
// 如果目的地是登錄,跳轉到主界面。否則不做理會
if (to.name === "login") {
next("/main");
} else {
next()
}
})
// token 無效
.catch((err) => {
next("/login");
// 清除token
localStorage.removeItem("token");
});
} else {
if (to.name !== "login") next("/login");
else next();
}
});
這樣每次刷新的時候,就會自動判斷token是否有效,否則就重新登錄。
其他問題
1 前端記得配置axios,防止每次請求均為不同的session。配置如下:
import axios from "axios";
axios.defaults.withCredentials = true;
2 退出及刪除session的邏輯這里不再贅述,大體相同。
