【背景】
目前在做一个前后端分离的 web 项目,后端使用的是 django 框架,所有的 API 都只返回 json ;就在这个过程中遇到了一个问题,那就是对于所有的 JsonResponse django 都不会主动设置 response 对象的 cookies ,这个就进一步使得 csrftoken 这个 cookie 值永远不会出现在 response 中。
【2、解决方案一】
这个方案的解决思路是:既然 django 不主动的去设置 csrftoken 的值,干脆自己设置它。
from django.utils.decorators import method_decorator from django.views.decorators.csrf import ensure_csrf_cookie class GetIDCView(View): """ 实现 IDC 信息的查询 """ def get(self,request,pk): logger.debug(f"查询所有的 idc ") qs = IDC.objects.all().values('name','city','id') # 把 QuerySet 变成列表 _lqs = [i for i in qs] rst = { 'message': '', 'code': 0, } rst['data'] = { 'idcs': _lqs } response = JsonResponse(rst) # 手功完成 set_cookie response.set_cookie('csrftoken','csrf-token-value') return response
写一个用于检查 cookie 的客户端程序
import requests if __name__ == "__main__": session = requests.Session() response = session.get("http://127.0.0.1:8080/hosts/idcs/") print(response.cookies)
查看返回的 cookie 值
python3 getcookie.py < RequestsCookieJar[ < Cookie csrftoken=csrf-token-value for 127.0.0.1/ > ] >
这个方案存在的问题:把设置 cookie 作为了业务逻辑的一部分,不方便维护。
【3、解决方案二】
这个方案的解决思路是:直接使用 django 使用的提供的装饰器,这个方案在 django 的官方文档上只是简单的提了一下(只有四行字),所以它的难点在于有没有认真的看过官方文档
from django.views import View from django.utils.decorators import method_decorator from django.views.decorators.csrf import ensure_csrf_cookie class GetIDCView(View): """ 实现 IDC 信息的查询 """ @method_decorator(ensure_csrf_cookie) def get(self,request,pk): # 如果 pk == None 说明是要查询出所有的 IDC 实例 logger.debug(f"查询所有的 idc ") qs = IDC.objects.all().values('name','city','id') # 把 QuerySet 变成列表 _lqs = [i for i in qs] rst = { 'message': '', 'code': 0, } rst['data'] = { 'idcs': _lqs } return JsonResponse(rst)
查看效果
python3 getcookie.py < RequestsCookieJar[< Cookie csrftoken=iQQhG2NETVTDnWTAVYBXji1ehLdWesKIGCCxTC1icyIapoS6LrpdUYOZc39qJsto for 127.0.0.1/ > ] >
这个方案的好处在于 View 只要处理业务逻辑就行了。
引用自:https://www.sqlpy.com/blogs/books/2/chapters/15/articles/53