Мои настройки (локальные) следующие:
- Vue.js, работающий на локальном хосте: 8080 (npm run serve)
- REST API, созданный с использованием Django на локальном хосте: 8000 (./manage-py runserver)
Чтобы это работало, я сделал следующие дополнения:
ALLOWED_HOSTS = [
...
'localhost',
'localhost:8000',
'localhost:8080',
]
INSTALLED_APPS = [
...
'rest_framework',
'corsheaders',
]
MIDDLEWARE = [
...
'django.contrib.sessions.middleware.SessionMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
...
]
CORS_ORIGIN_WHITELIST = (
'localhost:8080',
'localhost:8000',
)
CORS_ALLOW_CREDENTIALS = True
from corsheaders.defaults import default_headers
CORS_ALLOW_HEADERS = default_headers + (
'credentials',
)
Одна из моих функций API:
@ensure_csrf_cookie
def try_login(request):
# this is just to get the initial CSRF token:
if request.method == "GET" or request.method == "OPTIONS":
return JsonResponse({'status': 'ok'})
# else, an actual login request:
else:
data = JSONParser().parse(request)
user = authenticate(request, username=data['user'] , password=data['pass'])
if user is not None:
login(request, user)
return JsonResponse({'login_succ': 'ok'});
else:
return JsonResponse({'login_succ': 'fail'});
Наконец, в Vue:
api: function(endpoint, method, data) {
var headers = new Headers();
headers.append('content-type', 'application/json');
if (... this is not the first request ever ...)
{
csrftoken = document.cookie.replace(/(?:(?:^|.*;\s*)csrftoken\s*\=\s*([^;]*).*$)|^.*$/, "$1");
headers.append('X-CSRFToken', csrftoken);
}
method = method || 'GET';
var config = {
method: method,
body: data !== undefined ? JSON.stringify(data) : null,
headers: headers,
};
config['credentials'] = 'include';
return fetch(endpoint, config)
.then(response => response.json())
.catch((error) => { console.log(...); });
},
trylogin: function() {
// initial request: just to get the CSRF token
this.api(".../login/", "GET").then(
response => {
this.api(".../login/", "POST", {'username': ..., 'password': ...} ).then(
response => {
if ("login_succ" in response && res["login_succ"] == "ok")
{} // user is logged in
}
);
}
);
}
Что происходит сейчас, afaiu, так это то, что мой начальный запрос API (который не не должен указывать на конечную точку, равную последующему запросу POST, верно?) Получает токен CSRF в виде cookie. Каждый последующий запрос читает этот файл cookie и устанавливает заголовок X-CSRFToken . Сам cookie также отправляется в последующих запросах. Я не понимаю, зачем нужен токен в обоих местах.
Правильный ли этот подход? Все, что я сделал, необходимо? (Существуют ли избыточные части?) Меня особенно интересует способ получения токена в первую очередь и вообще его жизненный цикл.
Спасибо.