关于CRSF令牌的Django错误

时间:2017-10-29 17:40:23

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

我使用django作为后端的Web API,使用React JS作为前端的Web UI。用户将从Web UI注册,该UI将向django发送POST请求以注册用户详细信息。我想用CSRF保护注册视图。因此,我提出了以下步骤。

首先,一旦加载了注册页面,我就会发出一个虚拟GET请求来存储csrf标记,其代码如下所示。

handleSend(){
  let req = {
    url: 'http://localhost:9000/vcubes/retrieve_token/',
    method : 'GET',
    withCredentials: true
  }
  axios(req)
}

然后,当用户提交注册表单时,将触发另一个POST请求。

const data = JSON.stringify({
        'first_name': this.state.first_name,
        'last_name': this.state.last_name,
        'email': this.state.email,
        'contact_number': this.state.contact_number,
        'password1': this.state.password1,
        'password2': this.state.password2,
      })
      let req = {
        url: 'http://localhost:9000/vcubes/signup/',
        method : 'POST',
        headers: {
                'Content-Type': 'text/plain'
        },
        data: data
      }
      axios.defaults.headers.common['X-CSRF-TOKEN'] = this.getCookie('vcubes')

使用上面的代码,OPTIONS将首先发送到django,然后在django发回200 OK之后,将触发实际的POST请求。

enter image description here enter image description here

惊喜! Django表示我没有设置CSRF cookie。

Forbidden (CSRF cookie not set.): /vcubes/signup/
[30/Oct/2017 01:30:48] "POST /vcubes/signup/ HTTP/1.1" 403 2857

我的settings.py位于下方。 (我只向CORS和CSRF展示一些相关代码)

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'corsheaders',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'custom_user',
    'vcubes',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

CSRF_TRUSTED_ORIGINS = (
    'localhost:8000',
    '127.0.0.1:8000'
)

CSRF_COOKIE_NAME = 'vcubes'

CSRF_HEADER_NAME = 'HTTP_X_CSRF_TOKEN'

CORS_ORIGIN_ALLOW_ALL = True

CORS_ALLOW_CREDENTIALS = True

CORS_ORIGIN_WHITELIST = (
    'localhost:8000',
    '127.0.0.1:8000'
)


CORS_ALLOW_HEADERS = (
    'access-control-allow-credentials',
    'access-control-allow-origin',
    'access-control-request-method',
    'access-control-request-headers',
    'accept',
    'accept-encoding',
    'accept-language',
    'authorization',
    'connection',
    'content-type',
    'dnt',
    'credentials',
    'host',
    'origin',
    'user-agent',
    'X-CSRF-TOKEN',
    'X-CSRFToken',
    'x-requested-with',
)

在views.py

@ensure_csrf_cookie
def retrieve_token(request):
    return HttpResponse(status=200)

def signup(request):
    print request.META
    form = UserCreationForm(json.loads(request.body))
    # user = form.save(commit=False)
    # user.is_active = False
    # user.save()
    #
    # mail_subject = 'Activate your account.'
    # message = render_to_string('acc_active_email.html', {
    #     'name': user.get_full_name(),
    #     'domain': 'localhost:9000',
    #     'uid': urlsafe_base64_encode(force_bytes(user.pk)),
    #     'token': account_activation_token.make_token(user),
    # })
    # to_email = user
    # email = EmailMessage(
    #     mail_subject, message, to=[to_email]
    # )
    # email.send()
    return HttpResponse(status=200)

我花了一整天时间从谷歌和stackoverflow找出问题,但几乎没有得到任何帮助。请赐教!

1 个答案:

答案 0 :(得分:0)

您的帖子请求缺少withCredentials: true,这意味着您的CSRF Coo​​kie不会随请求一起发送。