django - Delphi IdHTTP 在 Django 创建的表单上发布

标签 django delphi http csrf indy

我正在将来自 delphi 的登录数据发布到在我的本地主机上运行的 django-created-form 上。像这样:

procedure TForm1.btnPostClick(Sender: TObject);
var
  IdHTTP: TidHTTP;
  auth: TStringList;
  test,token:string;
begin
  IdHTTP := TidHTTP.Create(nil);
  IdHTTP.Request.Accept         :='text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8';
  IdHTTP.Request.AcceptCharSet  :='iso-8859-1, utf-8, utf-16, *;q=0.1';
  IdHTTP.Request.AcceptEncoding :='deflate, gzip, identity, *;q=0';
  IdHTTP.Request.Connection     :='Keep-Alive';
  IdHTTP.Request.ContentType    :='application/x-www-form-urlencoded';

  token := IdHTTP.Get('http://localhost:8000/accounts/signup/');
  token := copy(token, AnsiPos('csrfmiddlewaretoken', token) + 28, 32);

  IdHTTP.Request.CustomHeaders.Clear;
  with IdHTTP.Request.CustomHeaders do
  begin
    AddValue('X-CSRFToken',token);
    Values['COOKIE']:='';
    //if IdHTTP2.CookieManager.CookieCollection.count > 0 then
    //  Add('COOKIE: '+token);
  end;

  try
    auth := TStringList.Create;
    auth.Add('csrfmiddlewaretoken='+ token);
    auth.Add('first_name=' + edtVorname.Text);
    auth.Add('last_name=' + edtName.Text);
    auth.Add('function=' + edtFunction.Text);
    auth.Add('company=' + edtCompany.Text);
    auth.Add('country=' + edtCountry.Text);
    auth.Add('email=' + edtEmail.Text);
    auth.Add('password1=' + edtPassword.Text);
    auth.Add('password2=' + edtPasswordAgain.Text);

    //IdHTTP.Request.CustomHeaders.AddValue('Accept-Language', 'en-EN');
    //IdHTTP.Request.CustomHeaders.AddValue('Referer',
    IdHTTP.post('http://127.0.0.1:8000/accounts/signup/', auth);
  except
  end;
end;

每当它到达帖子的行

 IdHTTP.post('http://127.0.0.1:8000/accounts/signup/', auth);

我收到 403 错误“禁止访问”。我的猜测是我发送了错误的 CSRF-Token
因为从 python 调试器我看到被困在

 if csrf_token is None:
            # No CSRF cookie. For POST requests, we insist on a CSRF cookie,
            # and in this way we can avoid all CSRF attacks, including login
            # CSRF.
            return self._reject(request, REASON_NO_CSRF_COOKIE)

但它应该如何呢?我需要如何发送这个 csrf-token?

P.S 好吧,我认为问题是默认情况下 HandleRedirects 设置为 True 并且它给了我 403。最新 Django 版本中的 cookievalue 通常称为 csrftoken 而不是 X-CSRFToken 我在这里是怎么做的。

最佳答案

您不应该自己设置 cookie。当带有表单的 Django 响应和 django.middleware.csrf.CsrfViewMiddleware 在您的中间件类列表中时(更多关于 https://docs.djangoproject.com/en/1.7/ref/contrib/csrf/ ),它应该已经设置 csrftoken cookie。因此,您只需读取此 cookie 的值并将其设置为 csrfmiddlewaretoken 表单字段。

另外不要忘记在您的请求中设置 UserAgent。如果没有 UserAgent,Indy(Delphi 2010)和 Django 1.8 将无法相互合作。

我不知道如何在重定向上添加 csrfmiddlewaretoken 字段,所以我没有重定向就做到了!

这是我的代码:

uses
  IdURI, IdCookie;

...

procedure TForm1.btnLoginClick(Sender: TObject);
var
  idHTTP: TIdHTTP;
  token: AnsiString;
  stream: TStringStream;
  params: TStringList;
  cookie: TidCookieRFC2109;
begin
  idHTTP := TIdHTTP.Create(nil);
  stream := TStringStream.Create;
  params := TStringList.Create;
  try
    idHTTP.AllowCookies := True;
    idHTTP.HandleRedirects := False;
    //even if HandleRedirects := False, you must have OnRedirect event (don't know why)
    idHTTP.OnRedirect := IdHttpOnRedirect;
    IdHTTP.Request.Accept         := 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8';
    IdHTTP.Request.AcceptCharSet  := 'iso-8859-1, utf-8, utf-16, *;q=0.1';
    IdHTTP.Request.AcceptEncoding := 'gzip, deflate, sdch';
    IdHTTP.Request.Connection     := 'Keep-Alive';
    IdHTTP.Request.ContentType    := 'application/x-www-form-urlencoded';
    idHTTP.Request.UserAgent      := 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.107 Safari/537.36';
    idHTTP.Request.CharSet        := 'utf-8';

    idHTTP.Get('http://www.ttaksa.si/login/');

    cookie := idHTTP.CookieManager.CookieCollection.Cookie['csrftoken', '.www.ttaksa.si'];
    token := cookie.Value;

    params.Values['csrfmiddlewaretoken'] := token;
    params.Values['username'] := txtUporabniskoIme.Text;
    params.Values['password'] := txtGeslo.Text;

    idHTTP.Post('http://www.ttaksa.si/login/', params, stream);

    idHTTP.Get('http://www.ttaksa.si/objekti/export/?zacetni_datum=23.7.2015-12:00:00&format=xml&indent=2', stream);

    stream.SaveToFile(txtFilename.Text);
    wbUvoz.Navigate('File://' + txtFilename.Text);
  finally
    idHTTP.Free;
    stream.Free;
    params.Free;
  end;
end;

procedure TForm1.IdHTTPOnRedirect(Sender: TObject; var dest: string;
  var NumRedirect: Integer; var Handled: boolean; var VMethod: TIdHTTPMethod);
begin
  Handled := True;
end;

关于django - Delphi IdHTTP 在 Django 创建的表单上发布,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30210396/

相关文章:

Oauth 登录后 django allauth 未创建用户帐户

python - 使用 Beautifulsoup 和 Mechanize 从元素中解析 href 属性值

python - 当从 Upstart 运行时没有获得环境变量时,Gunicorn + Django 不起作用

delphi - 基于无约束泛型类型创建对象实例

http - Mule 4 在 Dataweave 中设置 HTTP 状态

python - 类型错误... 'myModel' 对象不可迭代

德尔福印地 http 选项

delphi - Delphi 中按加载顺序生成表单/单元列表的最佳方法是什么?

javascript - 为什么在 angularjs 中 $http.post 的成功或错误回调函数没有正确执行

c++ - 从 C++ 代码与 servlet 交互