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',]