【问题标题】:Not persistent connection for flutter/dart http.Client()颤振/飞镖 http.Client() 的非持久连接
【发布时间】:2020-04-24 00:17:19
【问题描述】:

我有一个正在运行的 django-server,它与 sessions 一起工作。这里给出了一个来自我的 views.py 的简单示例,它应该足以重现我的问题:

def test(request):
    print("Session objects(")
    for k,v in request.session.items():
        print(k,v)
    print(")")
    request.session["a"] = "b"

所以这只是打印当前会话中的所有内容,然后在会话中保存一些虚拟数据。如果我第一次通过浏览器访问它,输出是

Session objects(
)

所以会话是空的,就像预期的那样。然后刷新站点后输出是:

Session objects(
a b
)

也如预期的那样,所以一切似乎都很好。

但现在我想将该网站与我的颤振应用程序一起使用。为此,我使用了 flutter packacke import 'package:http/http.dart' as http,如下所示:

var client = http.Client();

String host = ...; // just the ip:port to my host

void my_request() async {
  var response = await client.get(host + "/path/to/test/");
  response = await client.get(host + "/path/to/test/");
}

所以这应该做的就是两次请求我的网站,就像我之前在浏览器中手动做的那样。但是现在我的服务器只记录了两次:

Session objects(
)

所以很明显客户端有一个非持久连接,会话没有被保留。但是根据文档https://pub.dev/packages/http 这应该可以工作

如果您向同一个服务器发出多个请求,您可以使用客户端保持打开一个持久连接,而不是发出一次性请求

这是我的颤振/飞镖应用程序的问题还是我的服务器上的问题?它可能是颤振包中的一个大人物吗?

注意:我最初认为这可能是 csrf-authentication 的问题,所以在我的服务器上停用了它,但这并没有改变任何东西......

【问题讨论】:

  • peristenceConnection 属性的值是多少?如果为 False,请尝试将其设置为 True,看看是否有效。

标签: python django http flutter dart


【解决方案1】:

您不需要第 3 方库。这是相当少量的代码。因此,在第一个授权请求之后,服务器将在响应标头中使用关键字set-cookie 下的cookie 进行响应。有用的信息在 set-cookie 键的值中,从开始到第一次出现 ; 字符(稍后会详细介绍)。例如,set-cookie 的值可能如下所示:

sessionid=asfweggv7bet4zw11wfpb4u415yx; expires=Fri, 06 Nov 2020 11:14:40 GMT;

您需要保存它并在每次下一个授权请求中使用。

为了保存它,我创建了一个方法,您应该在第一个授权响应后调用它。您可以在每次响应后调用它(如果您有通用响应处理),因为如果服务器没有发送新的 cookie,它不会与现有 cookie 混淆。***

import 'package:flutter_secure_storage/flutter_secure_storage.dart';
const kCookie = 'my_fancy_cookie';
// ...
void _storeCookie(http.Response response) async {
  String rawCookie = response.headers['set-cookie'];
  if (rawCookie != null) {
    int index = rawCookie.indexOf(';');
    String cookie = (index == -1) ? rawCookie : rawCookie.substring(0, index);
    await FlutterSecureStorage().write(key: kCookie, value: cookie);
  }
}

然后在我发送请求之前,我将 cookie 添加到标题中:

// endpoint, payload and accessToken are defined earlier
cookie = await FlutterSecureStorage().read(key: kCookie);
http.Response response = await http.post(
  endpoint,
  body: json.encode(payload),
  headers: {
    'Content-Type': 'application/json',
    'Accept': 'application/json',
    'Authorization': 'Bearer ' + accessToken,
    'cookie': cookie,
  }
);

请记住在注销后从安全存储中清除 cookie。 :)

*** - 服务器可能会更改会话 ID(以减少我们还不需要考虑的点击劫持等事情),因此最好从每个响应中继续提取 cookie。

【讨论】:

    【解决方案2】:

    浏览器正在保存/发送 Django 会话 cookie。 Flutter 应用的 http 请求不是。

    “持久”连接并不意味着它会为您处理 cookie。你需要自己做,或者找一个第三方库来做。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-12-25
      • 2020-11-05
      • 2020-08-12
      • 1970-01-01
      • 1970-01-01
      • 2021-02-09
      • 2023-03-05
      相关资源
      最近更新 更多