【问题标题】:"403 CSRF cookie not set" when doing POST on Android, with CSRF_USE_SESSIONS = True (Django 1.11)在 Android 上执行 POST 时出现“403 CSRF cookie not set”,CSRF_USE_SESSIONS = True (Django 1.11)
【发布时间】:2018-02-11 14:58:09
【问题描述】:

晚上好,

this discussion 之后,我们面临一个新问题。我们正在尝试使用 Volley 库在 Android 上发出 POST 请求(登录)以发出 HTTP 请求。 /login/ 在 Postman 或 Advanced REST Client 上运行良好,但在使用 Volley 时却不行。我们已经看到许多其他人面临这个问题并试图在 SO 上找到答案,但唯一的答案是禁用 CSRF,我们真的不想这样做。

在 Postman 上,响应为 200 OK。
在 Android Volley 上,响应为 403 disabled : CSRF cookie not set

由于我们将 CSRF_USE_SESSIONS 设置为 True,因此对我们来说没有意义。

  • CSRF_USE_SESSIONS 在 Django 中为真
  • 用于在 Android 上发出 HTTP 请求的库是 Volley
  • 我们不想禁用 CSRF 保护/中间件(我指出这一点是因为其他帖子中谈论这个问题的许多答案都建议禁用 CSRF,但我们将它用于 Web 客户端和移动设备应用程序)

这是 Java 请求:

    private void loginPost(final String csrf) {
    RequestQueue queue = Volley.newRequestQueue(getActivity());
    String url = "https://api.ourapi.com/login/";


    JSONObject object = new JSONObject();

    try {
        object.put("username", "hello");
        object.put("password", "world");

        System.out.println(object);
    } catch (JSONException e) {
        Log.d("Dude", "RIIIIIIIIIIIIIIIIIIIP");
    }

    JsonObjectRequest jsonObjectRequest = new JsonObjectRequest
            (Request.Method.POST, url, object, new Response.Listener<JSONObject>() {

                @Override
                public void onResponse(JSONObject response) {
                    // response
                    System.out.println("######################################");
                    System.out.println(response);
                }
            }, new Response.ErrorListener() {

                @Override
                public void onErrorResponse(VolleyError error) {
                    // TODO Auto-generated method stub
                    System.out.println(error);
                }
            }
            ) {
        @Override
        public Map<String, String> getHeaders() throws AuthFailureError {
            Map<String, String>  params = new HashMap<String, String>();

            params.put("Accept", "application/json");
            params.put("X-CSRFToken", csrf);

            System.out.println(params);
            return params;
        }
    };
    queue.add(jsonObjectRequest);
}

这是基于 Django Login 类的视图:

class Login(LoginView):

form_class = AuthenticationForm
template_name = 'users/login.html'

def post(self, request, *args, **kwargs):
    if request.META.get('HTTP_ACCEPT') == 'application/json':
        form = self.get_form()
        if not form.is_valid():
            print(form.errors.as_text())
            return JsonResponse({'error': form.errors.as_text()}, status=400)
    return super().post(request, *args, **kwargs)

我们认为我们在 Volley 请求标头或其他地方遗漏了某些内容。你们能帮帮我们吗?

编辑:

这是我们的 CSRF 设置:

  • CSRF_COOKIE_AGE = 无
  • CSRF_COOKIE_DOMAIN = '.ourapi.com'
  • CSRF_COOKIE_HTTPONLY = 真
  • CSRF_COOKIE_SECURE = 真
  • CSRF_USE_SESSIONS = 真

【问题讨论】:

    标签: android django post cookies csrf


    【解决方案1】:

    在这里自我回答!

    我有点误解了 CSRF 和会话 cookie 在 Django 中的工作方式。在CsrfViewMiddlewareprocess_view函数中,当CSRF token为None时触发原因消息403 disabled - CSRF cookie not set(见here)。 csrf_token 值来自同一个类的 _get_token(request) 方法,但返回的值似乎是 None(见here)。

    我们所要做的就是简单地将会话 cookie 发送到服务器,并将标头中的 CSRF 令牌作为 X-CSRFToken !

    【讨论】:

      猜你喜欢
      • 2019-06-16
      • 2018-02-09
      • 2022-01-12
      • 2014-05-13
      • 1970-01-01
      • 2019-01-25
      • 2018-11-06
      • 1970-01-01
      • 2023-01-27
      相关资源
      最近更新 更多