如何在 Django RESTful API 和 React 中使用 csrf_token?

IT技术 python django reactjs django-rest-framework
2021-04-04 23:37:05

我以前在Django. 如果{csrf_token}Django模板中添加行Django处理csrf_token. 但是当我尝试使用Django REST Framework然后开发 API 时,我被卡住了。我如何添加和处理像 Django 模板这样csrf_tokenAPI(后端,使用开发的Django REST Framework)和React Native/React JS(前端)的功能?

2个回答

第一步是获取可以从 Django csrftoken cookie 中检索的 CSRF 令牌。

现在,您可以Django 文档中了解如何使用这个简单的 JavaScript 函数从 cookie 中获取 csrf 令牌:

function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = jQuery.trim(cookies[i]);
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}

现在,您可以通过调用该getCookie('csrftoken')函数来检索 CSRF 令牌

var csrftoken = getCookie('csrftoken');

接下来,您可以通过将检索到的令牌分配给 X-CSRFToken 标头,在使用 fetch() 发送请求时使用此 csrf 令牌。

  fetch(url, {
    credentials: 'include',
    method: 'POST',
    mode: 'same-origin',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json',
      'X-CSRFToken': csrftoken
    },
    body: {}
   })
  }

在 React Forms 中渲染 CSRF 令牌:

如果您使用 React 来呈现表单而不是 Django 模板,您还需要呈现 csrf 令牌,因为 Django 标记{ % csrf_token % }在客户端不可用,因此您需要创建一个使用该getCookie()函数检索令牌并呈现它的高阶组件以任何形式。

让我们在csrftoken.js文件中添加一些行

import React from 'react';

var csrftoken = getCookie('csrftoken');

const CSRFToken = () => {
    return (
        <input type="hidden" name="csrfmiddlewaretoken" value={csrftoken} />
    );
};
export default CSRFToken;

然后你可以简单地导入它并在你的表单中调用它

import React, { Component , PropTypes} from 'react';

import CSRFToken from './csrftoken';


class aForm extends Component {
    render() {

        return (
                 <form action="/endpoint" method="post">
                        <CSRFToken />
                        <button type="submit">Send</button>
                 </form>
        );
    }
}

export default aForm;

Django CSRF Coo​​kie

React 动态渲染组件,这就是为什么如果您使用 React 渲染表单,Django 可能无法设置 CSRF 令牌 cookie。Django 文档是这样说的:

如果您的视图未呈现包含 csrftoken 模板标记的模板,Django 可能不会设置 CSRF 令牌 cookie。这在表单被动态添加到页面的情况下很常见。为了解决这种情况,Django 提供了一个视图装饰器来强制设置 cookie:ensurecsrf_cookie()。

为了解决这个问题,Django 提供了 ensurecsrfcookie 装饰器,你需要将它添加到你的视图函数中。例如:

from django.views.decorators.csrf import ensure_csrf_cookie

@ensure_csrf_cookie
def myview(request):
我用过这个: var cookie = cookies[i].toString().replace(/^([\s]*)|([\s]*)$/g, ""); 而不是 var cookie = jQuery.trim(cookies[i]); 这样你就不需要 jQuery
2021-05-24 23:37:05
我使用 react js 作为前端,django 仅用于后端 api。react js的html是由react js自己渲染的,django只提供了调用api时的json数据。我在调用 django apis 后在 reactjs 页面上看到了 cookie,没有设置 cookie,为什么要设置它,因为 django 只是提供 json 数据而不是设置 cookie。那么在这种情况下我怎样才能获得 csrf cookie 值呢?
2021-05-26 23:37:05
cookies[i].trim() 更好,如果你能编辑你的帖子就好了:)
2021-05-31 23:37:05
@Yusuf 你找到解决方案了吗?我也在使用 react 来渲染页面
2021-06-01 23:37:05
@Davi -无论是通过使用CSRF fractalideas.com/blog/...或切换到令牌Django的诺克斯基础的认证是由Django的休息比默认令牌身份验证更好,也更接近真实世界的API github.com/James1345/django-rest-诺克斯
2021-06-18 23:37:05

我在react中使用了 jquery for ajax,所以在这种情况下,这是一个解决方案:

let csrfcookie = function() {  // for django csrf protection
            let cookieValue = null,
                name = "csrftoken";
            if (document.cookie && document.cookie !== "") {
                let cookies = document.cookie.split(";");
                for (let i = 0; i < cookies.length; i++) {
                    let cookie = cookies[i].trim();
                    if (cookie.substring(0, name.length + 1) == (name + "=")) {
                        cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                        break;
                    }
                }
            }
            return cookieValue;
};

$.ajax({
       type: "POST",
       beforeSend: function(request, settings) {
                    if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
                        request.setRequestHeader("X-CSRFToken", csrfcookie());
                    }
},

.... /// other codes