Django使用session管理(cookie)实现了一个用户登录和会话保持功能。如果需求不太复杂可以使用Django默认的登录功能。
1 安装django-cors-headers
首先需要安装django-cors-headers
pip install django-cors-headers
2 在settings中配置
需要按照django-cors-headers 官方说明进行配置。https://github.com/adamchainz/django-cors-headers
主要是以下几项:
from corsheaders.defaults import default_headersINSTALLED_APPS = [...,"corsheaders",...,
]MIDDLEWARE = [...,"corsheaders.middleware.CorsMiddleware","django.middleware.common.CommonMiddleware",...,
]# 这里写的是前端的地址,比如8080
CORS_ALLOWED_ORIGINS = ["https://example.com","https://sub.example.com","http://localhost:8080","http://127.0.0.1:9000",
]# 上面这个配置可以用下面的替换,直接允许所有的源
CORS_ALLOW_ALL_ORIGINS = True
# 这个是允许携带cookie
CORS_ALLOW_CREDENTIALS = True# 配置header允许的字段
CORS_ALLOW_HEADERS = [*default_headers,'withCredentials',
]SESSION_COOKIE_SAMESITE = "None"
SESSION_COOKIE_SECURE = True
3 在视图中使用Django提供的登录函数
https://docs.djangoproject.com/en/5.0/topics/auth/default/#django.contrib.auth.views.LoginView
from django.contrib.auth import authenticate, logindef my_view(request):username = request.POST["username"]password = request.POST["password"]user = authenticate(request, username=username, password=password)if user is not None:login(request, user)# Redirect to a success page....else:# Return an 'invalid login' error message....
这里注意,只有header中Content-Type
是x-www-form-urlencoded
才可以这样解析,如果是application/json
, 需要通过下面的方式:
data = json.loads(request.body)
username = data['username']
password = data['password']
4 使用fetch进行登录
在前端通过fetch或者axios发送请求,这里以fetch为例:
fetch(url, {headers: {'X-CSRFToken': csrftoken, //这个是可选的,如果禁用了csftoken则不需要。'Content-Type': 'x-www-form-urlencoded', //这里可以是application/json,后端需要方式二获取参数withCredentials: true //跨域时携带cookie},credentials: 'include', //要求携带cookie,否则无法维持会话body: JSON.stringify({username: xxx,password: xxx})
}).
then(res=>res.json()).
then(resJson=>{console.log(resJson) //这里处理登录结果
})
我们也可以包装为一个函数:
import Cookies from 'js-cookie'const sendRequest = (url, method, data)=>{const csrftoken = Cookies.get('csrftoken')const options = {method: method,headers: {'X-CSRFToken': csrftoken,'Content-Type': 'application/json', //这里可以是application/json,后端需要方式二获取参数withCredentials: true //跨域时携带cookie},credentials: 'include', //要求携带cookie,否则无法维持会话body: JSON.stringify(data)}if(method != 'GET' && data) {options.body = JSON.stringify(data)}return fetch(`http://localhost:8000/${url}`, options)
}
5 验证登录是否成功
如果登录成功,则前端发送的请求都会带有一个user,后端可以这样获取:
def my_view(request):id = request.user.id
如果登录失败,则前端获取的id为None,用户为匿名用户。
遇到的问题
- “Origin checking failed … does not match any trusted origins”
禁用csrf_token,具体做法:
- 建立一个middleware:
class DisableCSRFMiddleware(object):def __init__(self, get_response):self.get_response = get_responsedef __call__(self, request):setattr(request, '_dont_enforce_csrf_checks', True)response = self.get_response(request)return response
- 在settings中启用:
MIDDLEWARE = ['django.middleware.common.CommonMiddleware','django.middleware.security.SecurityMiddleware','django.contrib.sessions.middleware.SessionMiddleware','django.middleware.common.CommonMiddleware',#'django.middleware.csrf.CsrfViewMiddleware','myapp.middle.DisableCSRFMiddleware','django.contrib.auth.middleware.AuthenticationMiddleware','django.contrib.messages.middleware.MessageMiddleware','django.middleware.clickjacking.XFrameOptionsMiddleware',]