【问题标题】:How to add CSRF token to Angular 8 post request from Django 2.2如何将 CSRF 令牌添加到来自 Django 2.2 的 Angular 8 发布请求
【发布时间】:2020-02-04 14:07:11
【问题描述】:

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

但问题在于 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 Uncaught 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

【问题讨论】:

  • Angular 应用程序是否与 Django 在同一个域上提供服务?如果没有,那么你真的不需要 csrf,你可以只检查来源(跨域请求中总是存在的)。
  • Angular 开启 http://localhost:4200/ ang Django 开启 http://localhost:8000/
  • @GwynBleidD 我使用 Cross-Origin,我更新了问题,请再次检查。

标签: python django angular csrf


【解决方案1】:

你可以用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';

【讨论】:

  • 我应该把你提到的第二个代码放在哪里?
  • 我使用 angular 8
【解决方案2】:

所以我为此使用了这个名为 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);

在进行 post 调用时,我们正在使用这些标头

【讨论】:

    猜你喜欢
    • 2016-09-19
    • 2017-12-19
    • 2019-12-22
    • 2018-08-09
    • 2020-04-19
    • 2018-05-08
    • 1970-01-01
    • 2015-07-30
    • 2015-10-07
    相关资源
    最近更新 更多