首页 文章

在 flutter 升级后,Dart HttpClient 具有基本身份验证问题

提问于
浏览
0

经过大量的浏览和阅读文档后,我遇到了这个回答,直到我升级了。

我目前的问题是凭据无法到达我的服务器。 IntelliJ 错误:

I/FlutterActivityDelegate( 6944): onResume setting current activity to this
D/EGL_emulation( 6944): eglMakeCurrent: 0xa7f852a0: ver 2 0 (tinfo 0xa7f83250)
I/flutter ( 6944): doing login with credentials:: W and T
I/flutter ( 6944): my_response is:: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
I/flutter ( 6944): <title>429 Too Many Requests</title>
I/flutter ( 6944): <h1>Too Many Requests</h1>
I/flutter ( 6944): <p>1 per 1 minute</p>
E/flutter ( 6944): [ERROR:topaz/lib/tonic/logging/dart_error.cc(16)] Unhandled exception:
E/flutter ( 6944): type '(Exception) => void' is not a subtype of type '(Object) => FutureOr<dynamic>'

我的请求的服务器输出是:

credentials::  - 
 192.168.1.175 - - [12/May/2018 10:56:23] "GET /users/login HTTP/1.1" 401 -
 192.168.1.175 - - [12/May/2018 10:56:23] "GET /users/login HTTP/1.1" 429 -

LE:“凭证:: - ”是在服务器的身份验证级别完成的打印。 LLE:卷曲请求工作得很好

curl -u 123456:password http://localhost:5000/users/login 
{
 "is_logged_in": true, 
 "last_login": 1525980360
}

回应是:

credentials:: 123456 - password
127.0.0.1 - - [12/May/2018 13:00:50] "GET /users/login HTTP/1.1" 200 -

我使用与上面提供的链接完全相同的代码。

1 回答

  • 4

    以下是在评论中结束讨论的摘要答案。

    似乎Too Many Requests错误可能是由 HTTP 客户端与需要授权的服务器通信的典型行为触发的。

    GET ->
        <- 401 Unauthorized + scheme + realm (and nonce if applicable)
    GET with Authorization header ->
        <- 200 OK (if credentials are valid)
    

    似乎服务器可能已将第一个 GET/401 计入某种每分钟请求的限制。

    但是,来自 curl 的请求是成功的,可能是因为 curl 抢先发送了带有第一个 GET 的 Authorization 标头,而不是等待被问到 401.只要授权方案为Basic,它就可以执行此操作,因为它不需要来自服务器的任何信息。 (它无法与Digest一起使用,因为如果没有与 401.)一起发送的随机数,它无法计算 Authorization 标头

    所以问题出现了,有没有办法在package:http中抢先发送 Basic auth?

    正常方式 - 仅响应 401 发送

    // create an IOClient with authentication
    HttpClient inner = new HttpClient();
    inner.authenticate = (uri, scheme, realm) {
      inner.addCredentials(
          uri, realm, new HttpClientBasicCredentials(username, password));
    };
    http.IOClient client = new http.IOClient(inner);
    
    // and use it like this
    http.Response response = await client.get('https://api.somewhere.io');
    // todo - handle the response
    

    抢先方式 - 仅适用于基本身份验证

    // use the normal http.get method, but add the header manually, with every request
    http.Response response = await http.get(
      'https://api.somewhere.io',
      headers: {'authorization': basicAuthenticationHeader(username, password)},
    );
    // todo - handle the response
    

    用实用方法

    String basicAuthenticationHeader(String username, String password) {
      return 'Basic ' + base64Encode(utf8.encode('$username:$password'));
    }
    

相关问题