从安全角度来看,我不确定这个实现是否完全正确,但我想写这篇文章,因为我发现设置 django 并使用 csrf 做出反应时存在一些问题。

我在用着:

  • Django 4.0

  • 反应 17

  • django-cors-headers

zoz100005 axios

这是我为文件setting.py设置的

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'corsheaders', //<------cors
    'api'
]

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

CORS_ALLOW_CREDENTIALS = True
CORS_ALLOWED_ORIGINS=["http://localhost:3000", "http://127.0.0.1:3000"]
CSRF_TRUSTED_ORIGINS = ["http://localhost:3000", "http://127.0.0.1:3000"]

这是我获取 csrf 令牌的观点,使用装饰器 ensure_csrf_cookie,将在 http 响应中添加一个 set-cookie,因此我们将在浏览器中找到我们的 csrftoken cookie

from django.views.decorators.csrf import ensure_csrf_cookie
@ensure_csrf_cookie
def get_csrf(request):
    return JsonResponse({})

对于前端,在我们请求获取令牌之前调用我们的视图很重要,如果令牌已经存在,则将更新过期时间。

const get_csrf = () => axios.get('http://localhost:8000/api/get_csrf').then(res => {})

获得 cookie 后,我们可以执行 POST

axios.defaults.xsrfCookieName = 'csrftoken'
axios.defaults.xsrfHeaderName = 'X-CSRFToken'
axios.defaults.withCredentials = true
axios.post('http://localhost:8000/api/upload_data', { 'test': 'ok' }).then(res => {
    console.log(res)
}).catch(err => {
    console.log(err)
})

axios.defaults.xsrfCookieName u003d 'csrftoken'

axios.defaults.xsrfHeaderName u003d 'X-CSRFToken'

如果您想手动设置,将为您自动设置标头(对于每个请求),您可以通过这种方式获取 csrf 令牌

// from django website https://docs.djangoproject.com/en/4.0/ref/csrf/

function getCookie(name) {
    let cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        const cookies = document.cookie.split(';');
        for (let i = 0; i < cookies.length; i++) {
            const cookie = cookies[i].trim();
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}
const csrftoken = getCookie('csrftoken');

或使用这个库

  • npm i js-cookie

  • npm i@types/js-cookie(如果您使用的是打字稿)

并手动设置http post请求的标头

const csrftoken = Cookies.get('csrftoken')
axios.post('http://localhost:8000/api/upload_data',
    { 'body_data': 'ok' },
    { headers: { 'X-CSRFToken': csrftoken }}
).then(res => {
    console.log(res)
}).catch(err => {
    console.log(err)
})
Logo

学AI,认准AI Studio!GPU算力,限时免费领,邀请好友解锁更多惊喜福利 >>>

更多推荐