提交无法登陆,打开F12调试工具查看ajax返回信息:403 CSRF cookie not set.
网上给出的大体是3种解决方案
MIDDLEWARE = [
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
#'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
import re
class IgnorecsrfMiddleware(object):
def process_request(self, request, **karg):
if re.match(r'^/api/login$', request.path):
request.csrf_processing_done = True
return None
然后在settings.py中加入这个中间件
MIDDLEWARE = [
'mysites.functions.IgnorecsrfMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
但是我测试发现报错:TypeError: object() takes no parameters。
解决思路:
类IgnorecsrfMiddleware的父类是object,它提示 object() takes no parameters。意思是object
的__init__
没有参数,总的来说不能直接使用object,那么我们可以重写__init__
,但是这样比较麻烦,而且可能出现其他错误,那我们来看看其他中间件是怎么定义的
from django.utils.deprecation import MiddlewareMixin
class CsrfViewMiddleware(MiddlewareMixin):
# more code...
class XFrameOptionsMiddleware(MiddlewareMixin):
# more code...
我们可以看到,大都是使用Django的MiddlewareMixin作为父类,那么我们也尝试一下直接将MiddlewareMixin作为我自定义中间件的父类,结果当然是成功了啊。
下面贴上代码:
settings.py
#more code
MIDDLEWARE = [
'OpsMS.functions.IgnorecsrfMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
#more code
functions.py
import re
from django.utils.deprecation import MiddlewareMixin
class IgnorecsrfMiddleware(MiddlewareMixin):
def process_request(self, request, **karg):
if re.match(r'^/api/login$', request.path):
request.csrf_processing_done = True
return None
如果你有多个url需要绕过检测,可以在定义一个列表,然后用for循环遍历,或者通过正则来匹配(如:需要绕过csrf的,统一用 /api/IgnoreCsrf/xxxx
这种格式)
更新:
其实上面的方法都不能解决我的CRSF的问题,后来发现了一个临时解决crsf问题的方法:
在每个有post的地方加入一个装饰器就可以解决了:
@csrf_exempt