Джанго, CORS, CSRF - я делаю это правильно? - PullRequest
0 голосов
/ 02 января 2019

Мои настройки (локальные) следующие:

  • 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 также отправляется в последующих запросах. Я не понимаю, зачем нужен токен в обоих местах.

Правильный ли этот подход? Все, что я сделал, необходимо? (Существуют ли избыточные части?) Меня особенно интересует способ получения токена в первую очередь и вообще его жизненный цикл.

Спасибо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...