angularjs 使用CSRF_COOKIE_HTTPONLY将Django CSRF令牌传递给Angular

kse8i1jr  于 2022-10-31  发布在  Angular
关注(0)|答案(2)|浏览(182)

在Django中,当CSRF_COOKIE_HTTPONLY设置为True时,CSRF cookie会获得httponly标志,这从安全的Angular 来看是可取的,但它打破了将此cookie添加到httpProvider的标准Angular 解决方案,如下所示:

$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';

在Django 1.9中,有一个变通方案,你可以直接将cookie传递给应用,方法是在模板中添加以下内容:

<script>
    window.csrf_token = "{{ csrf_token }}";
</script>

把这个放进Angular 应用程序:

angularApp.config(["$httpProvider", function($httpProvider) {
    $httpProvider.defaults.headers.common["X-CSRFToken"] = window.csrf_token;
}]

不幸的是,在Django 1.10+中,这不适用于单页Angular 应用,因为CSRF cookie在每次请求后都会改变。如何在CSRF_COOKIE_HTTPONLY设置打开的情况下,从Angular向Django 1.10+发出帖子请求?

**注意:**禁用CSRF保护不是可接受的答案。

hrysbysz

hrysbysz1#

Django对此有一个文档化的解决方案,任何Javascript都可以从DOM中获取CSRF令牌,即使CSRF_COOKIE_HTTPONLY被启用,只要CSRF令牌在DOM中。

第1步:我添加了一个标记,让Django中间件把csrf标记放到DOM中


# Django put CSRF token to DOM

{% csrf_token %}

步骤2:实作HttpInterceptor以从DOM取得csrf

import { Injectable } from '@angular/core';
import { HttpEvent, HttpRequest, HttpHandler, HttpInterceptor } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable()
export class DjangoCSRFInterceptor implements HttpInterceptor {
  intercept(httpRequest: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const token = (
      document.querySelector('[name=csrfmiddlewaretoken]') as HTMLInputElement
    ).value;
    return httpRequest.clone({ headers: httpRequest.headers.set('X-CSRFToken, token) });
  }
}

步骤3:将HttpInterceptor放到您的Angular模块提供程序中

providers: [
  { provide: HTTP_INTERCEPTORS, useClass: DjangoCSRFInterceptor, multi: true }
]
dphi5xsq

dphi5xsq2#

我认为这个问题在这次讨论中得到了很好的回答。
https://groups.google.com/forum/#!topic/django-developers/nXjfLd8ba5k
https://code.djangoproject.com/ticket/27534
CSRF_COOKIE_HTTPONLY不为单页应用程序提供任何额外的安全性。

var csrftoken = getCookie('csrftoken');
if (csrftoken === null) {
    csrftoken = $('input[name="csrfmiddlewaretoken"]').val();
    if (csrftoken === null) {
        console.log('No csrf token');
    }
}

然而,无论是或如果你是暴露csrftoken为您的应用程序平静没有什么阻止恶意用户采取它和使用它,以及.如果你是运行一个单页应用程序,你不妨设置CSRF_COOKIE_HTTPONLY=假,根据下面的评论:
Gavin Wahl 2015年5月4日
为什么呢?你不能只是从不同的域中用ajax获取东西。
我说的是一个单一的域。在一个不包含CSRF令牌的页面上注入javascript可以获取同一个域上的不同页面来获得它。
如果您已经将javascript注入到受害者页面(XSS)中,则不需要获取CSRF令牌,您已经获得了更大的控制权。
嗯,HttpOnly标志是为了减少攻击者在已经可以注入javascript时所造成的损害。但是我同意--对javascript隐藏CSRF标记并没有以任何方式增加安全性,但是文档暗示它会增加安全性。我想在文档中清楚地说明这个设置没有任何有意义的效果。
如果您仍然认为您有一个有效的攻击媒介,请将其发送到secu...@ djangoproject.com并添加更多的说明。
没有攻击媒介。这只是误导性的文档。

相关问题