Django关于CRSF令牌的错误 [英] Django bug on CRSF token

查看:187
本文介绍了Django关于CRSF令牌的错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将django用作后端的Web API,并将React JS用作前端的Web UI。用户将通过Web UI进行注册,这将向django发送POST请求以注册用户详细信息。我想使用CSRF保护注册视图。因此,我给出下面的步骤。

I am using django as web API for backend and React JS as web UI for frontend. User will sign up from web UI which will send a POST request to django to register with the user details. I want to protect the signup view with CSRF. Therefore I come out with steps below.

首先,一旦加载了注册页面,我就会触发一个虚拟的 GET 请求使用以下代码存储csrf令牌。

First, once the sign up page is loaded, I fire a dummy GET request to store the csrf token with code below.

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

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

Then, when user submit the signup form, another POST request will be fired.

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请求。

With the code above, an OPTIONS will be sent to django first and then after django send back a 200 OK, then the actual POST request will be fired.

< a href = https://i.stack.imgur.com/l1L2S.png rel = nofollow noreferrer>

惊喜! Django声明我未设置CSRF cookie。

Surprise! Django stated that I do not set 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相关的代码)

My settings.py is below. ( I only show some related code to CORS and 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)

我已经花费了一整天的时间从Google和stackoverflow上找出问题,但几乎没有得到任何帮助。

I have been spending whole day to find out the problem from google and stackoverflow but hardly get any help. Please enlighten me!

推荐答案

您缺少 withCredentials:true 发布请求,这意味着您的CSRF cookie不会随请求一起发送。

You are missing withCredentials: true for your post request, which means that your CSRF cookie is not sent with the request.

这篇关于Django关于CRSF令牌的错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆