【问题标题】:How to cURL an Authenticated Django App?如何卷曲经过身份验证的 Django 应用程序?
【发布时间】:2014-02-13 21:40:34
【问题描述】:

我想用 cURL 测试一些 API。我尝试按如下方式进行 GET:

curl --user username:password --request GET http://my_domain/get_result/52d6428f3ea9a008358ad2d8/

在服务器上,它显示一个“302”(这意味着重定向,对吗?)。我猜它重定向到“登录/”页面。

完成这项工作的正确方法是什么?

编辑:我试过了:

curl -c cookies.txt -b cookies.txt -L -d @login_form.txt http://my_domain/login/

其中 login_form.txt 包含“username=username&password=password&this_is_the_login_form=1”。不工作。没有生成 cookies.txt 文件。并且没有登录发生。您能告诉我您是如何使用 cURL 实现登录 Django 的吗?

【问题讨论】:

    标签: django rest authentication curl


    【解决方案1】:

    在 curl 请求中传递用户名:密码仅适用于 HTTP 身份验证,这不是当今大多数网站进行身份验证的方式。相反,您必须发布到登录页面,获取 cookie,然后在请求所需页面时将其传回。

    【讨论】:

      【解决方案2】:

      这是一个完全编码的答案。解决方案的思路是:

      1. 您必须先使用 GET 访问登录页面才能生成 cookie 文件,
      2. 然后从 cookie 文件中解析出 CSRF 令牌
      3. 并使用 POST 请求进行登录,使用 -d 传递数据。

      之后,您可以始终使用数据中的 CSRF 令牌 ($DJANGO_TOKEN) 或自定义 X-CSRFToken 标头来执行任何请求。要退出,只需删除 cookie 文件。

      请注意,您需要一个引用者 (-e) 才能使 Django 的 CSRF 检查满意。

      LOGIN_URL=https://yourdjangowebsite.com/login/
      YOUR_USER='username'
      YOUR_PASS='password'
      COOKIES=cookies.txt
      CURL_BIN="curl -s -c $COOKIES -b $COOKIES -e $LOGIN_URL"
      
      echo -n "Django Auth: get csrftoken ..."
      $CURL_BIN $LOGIN_URL > /dev/null
      DJANGO_TOKEN="csrfmiddlewaretoken=$(grep csrftoken $COOKIES | sed 's/^.*csrftoken\s*//')"
      
      echo -n " perform login ..."
      $CURL_BIN \
          -d "$DJANGO_TOKEN&username=$YOUR_USER&password=$YOUR_PASS" \
          -X POST $LOGIN_URL
      
      echo -n " do something while logged in ..."
      $CURL_BIN \
          -d "$DJANGO_TOKEN&..." \
          -X POST https://yourdjangowebsite.com/whatever/
      
      echo " logout"
      rm $COOKIES
      

      我有一个更安全的代码版本,它使用一个文件来提交 POST 数据,作为 GitHub 上的 Gist:django-csrftoken-login-demo.bash

      关于 Django 的 CSRF 令牌的有趣背景阅读位于 docs.djangoproject.com

      【讨论】:

      • 我不得不说这拯救了我的一天。虽然现在没有推荐人它工作正常..
      • " sed 's/^.*csrftoken\s*//' " 在 csrf 值之前放置了一个额外的空格。这就是为什么我改用“ awk {'print $7'} ”。
      • 在 macOS 上,我最终在令牌前面多了一个标签——所以我按照this super user post 中的建议将\s 替换为[[:space:]]。另外,我不得不修改登录 URL,因为我得到了 302。
      • 在 MacOs 上,使用 sed 's/^.*csrftoken[[:blank:]]*//') 对我有用。现在我收到CSRF Failed: CSRF token missing or incorrect.。任何想法如何解决?
      • 如果您在标题中包含Content-Type: application/json,这将不起作用。
      【解决方案3】:

      实际上@Paterino 的答案是正确的,但它不适用于 sed 的每个实现。取而代之的是sed 's/^.*csrftoken\s*//'),我们可以使用更老式的sed 's/^.*csrftoken[[:blank:]]*//')。 MacOSX 的 curl 不使用转义,所以 \n\t\s 根本不起作用。

      【讨论】:

      • 一旦你有足够的reputation,你就可以在任何帖子上comment。还要检查这个what can I do instead
      • 感谢您指出这一点。答案是关于一般方法,实现细节参考 sed 的 GNU 版本(从 Linux 开始),这只是一个示例。我有一个要点让 GNU sed 在 Mac 上也成为默认值:gist.github.com/bittner/5436f3dc011d43ab7551
      • Nice 看起来是完美的解决方案,我稍后会尝试。我的帖子或多或少地扩展了您的答案以及其他可能像我一样挣扎的人。
      【解决方案4】:

      要将令牌用于获取请求,请使用

      $CURL_BIN \
          -H "$DJANGO_TOKEN" \
          -X GET https://yourdjangowebsite.com/whatever/
      

      我尝试将 -d 与 -X GET 一起使用,但它导致服务器端出现奇怪的套接字行为(Heruko H18 错误)。

      【讨论】:

        猜你喜欢
        • 2014-07-15
        • 1970-01-01
        • 2019-03-08
        • 1970-01-01
        • 2016-11-30
        • 1970-01-01
        • 2018-09-04
        • 1970-01-01
        相关资源
        最近更新 更多