如何从Django 2.2向Angular 8发布请求添加CSRF令牌

时间:2019-10-07 09:29:42

标签: python django angular csrf

我有一个带有Django后端和angular前端的应用程序。 现在,这些相互连接,我可以从Django获取数据并在Angular中显示。还要向Django发送发布请求。

但是问题在于Django中的CSRF令牌。我在Django中禁用了CSRF中间件,并完全禁用了请求过程,但是我知道这是不安全的。

执行发布请求的方法。

loadQuestion(id): Observable<any> {
    const body = {'choice': 'teseted with post method'};
    return this.http.post(this.baseUrl + id + '/vote', {headers: this.header, withCredentials: true, });
  }

我根据此link进行了一些更改。

HttpClientXsrfModule.withConfig({ cookieName: 'csrftoken', headerName: 'X-CSRFToken' })

但我收到此错误。

  

app.module.ts:26未捕获的TypeError:_angular_common_http__WEBPACK_IMPORTED_MODULE_3 __。HttpClientXsrfModule.withConfig不是函数

所以我根据此Link

进行了更改

HttpClientXsrfModule.withOptions({ cookieName: 'csrftoken', headerName: 'X-CSRFToken' })

这是我的Django函数,用于返回数据,正如我在禁用CSRF中间件时所说的那样,它可以正常工作,所以我应该修复CSRF问题并将其与Angular请求一起传递。

def vote(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    try:
        selected_choice = question.choice_set.get(pk=4)
    except (KeyError, Choice.DoesNotExist):
        # Redisplay the question voting form.
        return HttpResponse("You didn't select a choice.")
    else:
        selected_choice.votes += 1
        selected_choice.save()
        # Always return an HttpResponseRedirect after successfully dealing
        # with POST data. This prevents data from being posted twice if a
        # user hits the Back button.
        return HttpResponse(request)

我评论的中间件代码:

'django.middleware.csrf.CsrfViewMiddleware'

,错误为CSRF verification failed. Request aborted.

更新

我使用CORS Origin,这是我的Django配置

CORS_ORIGIN_ALLOW_ALL = True

CSRF_COOKIE_SECURE = False
CSRF_USE_SESSIONS = False

CORS_ORIGIN_ALLOW_ALL = True

CORS_ALLOW_HEADERS = (
    'accept',
    'accept-encoding',
    'authorization',
    'content-type',
    'dnt',
    'origin',
    'user-agent',
    'x-csrftoken',
    'x-requested-with',
    'X-CSRFToken',
    'x-csrftoken',
    'X-XSRF-TOKEN',
    'XSRF-TOKEN',
    'csrfmiddlewaretoken',
    'csrftoken',
    'X-CSRF'
)

CORS_ALLOW_CREDENTIALS = True

2 个答案:

答案 0 :(得分:0)

您可以使用csrf_exempt

包装视图
from django.views.decorators.csrf import csrf_exempt

@csrf_exempt
def vote():
...

“如果您使用的是AngularJS 1.1.3及更高版本,则只需使用Cookie和标头名称配置$ http提供程序即可:”

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

答案 1 :(得分:0)

因此,我使用了一个名为ngx-cookielink的库。 安装它,然后将其添加到service.ts中。

import {CookieService} from 'ngx-cookie';

constructor(private http: HttpClient, private _cookieService: CookieService) {
  let csrf = this._cookieService.get("csrftoken");
  if (typeof(csrf) === 'undefined') {
    csrf = '';
  }
  this.httpOptions = {
    headers: new HttpHeaders({'X-CSRFToken': csrf}),
  };
}

public postCall(payload){
  return this.http.post('/yourapi/', payload, this.httpOptions);
}

说明:

let csrf = this._cookieService.get("csrftoken");

此行从cookie中获取csrf令牌

 headers: new HttpHeaders({'X-CSRFToken': csrf}),

此行将csrf的值添加到HttpHeaders中。

this.http.post('/yourapi/', payload, this.httpOptions);

在进行帖子通话时,我们正在使用这些标题