Django,CORS,CSRF-我做对了吗?

时间:2019-01-02 13:39:53

标签: django django-rest-framework cors csrf django-cors-headers

我的设置(本地)如下:

  • 在localhost:8080上运行的Vue.js(npm运行服务)
  • 使用Django在localhost:8000(./manage-py runserver)上运行的REST API构建

为了使其能够正常工作,我添加了以下内容:

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本身也将在后续请求中发送。我不明白为什么两个地方都需要令牌。

这种方法正确吗?我所做的一切都必要吗? (有多余的部分吗?)我对首先应该获取令牌的方式特别感兴趣,并且通常与令牌的生命周期有关。

谢谢。

0 个答案:

没有答案