首页 > 解决方案 > Flutter http Post - StatusCode 401 - 重复响应

问题描述

我在 Flutter 中的 Http Post 请求遇到了一些问题。我必须连接到 PHP Web 服务(使用标头)并发布一些用户/密码信息以获得响应(此处为用户信息)。我相信我已经接近解决方案,但是StatusCode 401尽管当我尝试使用 Postman(使用相同的凭据)时它可以工作,但我仍然得到一个响应。

这是我调用的函数的代码:

Future<http.Response> post() async {

  var url = "https://www.monadresse/login.php";
  String password = "xxx";
  String username = "yyy";
  //var bytes = utf8.encode("$username:$password");
  var bytes = "$username:$password";
  String userNameUser = "www";
  String passwordUser = "zzz";
  var passwordUserEncoded = base64.encode(utf8.encode(passwordUser));
//var passwordUserEncoded = base64.encode(passwordUser);
  var headers = {
    "Authorization": "Basic $bytes",
    "Content-Type": "application/json",
  };
  var requestBody = json.encode({ 'user': userNameUser, 'password': passwordUserEncoded});
  print(headers);
  print(requestBody);

  final http.Response response = await http.post(
    url,
    body: requestBody,
    headers: headers,
  );
  if(response.statusCode == 200){
    var responseJson = json.decode(response.body);
    print(Utf8Codec().decode(response.bodyBytes));

    print("Body: " + responseJson);}

  print(bytes);
  print(passwordUserEncoded);
  print(response.statusCode);
  print("Fini");
}

另一件奇怪的事情(读作“我不明白”)......我添加了一些打印件以了解正在发生的事情,正如您在下文中看到的那样,前 2 个打印件(位于请求之前)首先打印两次之后,最后 3 次打印也重复两次。

flutter: {Authorization: Basic yyy:xxx, Content-Type: application/json}
flutter: {"user":"www","password":"zzz"}
flutter: {Authorization: yyy:xxx, Content-Type: application/json}
flutter: {"user":"www","password":"zzz}
flutter: yyy:xxx
flutter: zzz
flutter: 401
flutter: Fini
flutter: yyy:xxx
flutter: zzz
flutter: 401
flutter: Fini

由于我在网上找不到解决方案,我非常希望有人能帮助我。

标签: phphttpflutter

解决方案


如评论中所述,此问题的原因是'username:password'授权标头中使用的未编码为 base64。

这是使用Postman 的测试端点进行基本身份验证的工作示例。用户名是postman,密码是password

import 'dart:io';

import 'package:flutter/material.dart';

import 'package:http/http.dart' as http;
import 'dart:convert' show utf8, base64;

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  var _usernameTextController = TextEditingController();
  var _passwordTextController = TextEditingController();
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Container(
          padding: EdgeInsets.all(16.0),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              TextFormField(
                controller: _usernameTextController,
                decoration: const InputDecoration(
                  labelText: 'Username',
                ),
              ),
              TextFormField(
                controller: _passwordTextController,
                obscureText: true,
                decoration: const InputDecoration(
                  labelText: 'Password',
                ),
              ),
              ElevatedButton(
                child: Text('Login'),
                onPressed: _doLogin(_usernameTextController.text, _passwordTextController.text),
              )
            ],
          ),
        ),
      ), 
    );
  }

  _doLogin(String username, String password) {
    if (username.trim().isEmpty || password.trim().isEmpty) {
      debugPrint('Either username or password is empty');
    } else {
      _login(username, password)
          .then((value) => debugPrint('Login finished $value'))
          .catchError((error) => debugPrint('Login error: $error'));
    }
  }

  Future _login(String username, String password) async {
    // 'username:password' is base64 encoded
    var authHeader = '${base64.encode(utf8.encode('$username:$password'))}';
    debugPrint('userpass: ${username + password}');
    debugPrint('authHeader: $authHeader');
    final response = await http.get(
      'https://postman-echo.com/basic-auth',
      headers: {HttpHeaders.authorizationHeader: "Basic $authHeader"},
    );
    if (response.statusCode == 200) {
      // If the server did return a 200 OK response,
      // then parse the JSON.
      return response.body;
    } else {
      // If the server did not return a 200 OK response,
      // then throw an exception.
      throw Exception(
          'Failed to login [${response.statusCode}] ${response.body}');
    }
  }
}

推荐阅读