在Flutter中发布带有Cookie的请求

时间:2018-09-25 14:26:29

标签: post cookies request dart flutter

我正在尝试将Cookie添加到我的请求中:

在这里,我收到csrftoken的{​​{1}}请求:

GET

在这里,我尝试使用Dio软件包执行 Future<String> getCsrftoken() async{ var response = await http.get(Uri.encodeFull('http://test/accounts/login/')); var csrftoken = response.headers.remove('set-cookie').substring(10,74); //csrf 64 chars return csrftoken; } POST)请求。

application/x-www-form-urlencoded

我得到403状态代码,因为我需要添加为Cookie getSessionId() async { var csrf = await getCsrftoken(); var cj = new CookieJar(); List<Cookie> cookies = [new Cookie("csrftoken", csrf)]; cj.saveFromResponse(Uri.parse("http://test/accounts/login/"), cookies); List<Cookie> results = cj.loadForRequest(Uri.parse("http://test/accounts/login/")); var dio = new Dio(new Options( baseUrl: "http://test/accounts/login/", connectTimeout: 5000, receiveTimeout: 100000, // 5s headers: { }, contentType: ContentType.JSON, // Transform the response data to a String encoded with UTF8. // The default value is [ResponseType.JSON]. responseType: ResponseType.PLAIN )); Response<String> response; response = await dio.post("", data: { "username": "username", "password": "password", "csrfmiddlewaretoken" : getCsrftoken() }, // Send data with "application/x-www-form-urlencoded" format options: new Options( contentType: ContentType.parse("application/x-www-form-urlencoded")), ); print(response.statusCode); }

我应该如何进行?

2 个答案:

答案 0 :(得分:2)

来自Dio Dart API Docs

Cookie Manager

您可以使用cookieJar管理请求/响应cookie。

dio cookie管理API基于撤回的cookie_jar。

您可以创建一个CookieJar或PersistCookieJar来自动管理cookie,并且默认情况下dio使用CookieJar,这会将cookie保存在RAM中。如果要保留cookie,可以使用PersistCookieJar类,示例代码如下:

var dio = new Dio();
dio.cookieJar=new PersistCookieJar("./cookies");

PersistCookieJar是一个cookie管理器,它实现RFC中声明的标准cookie策略。 PersistCookieJar将cookie保留在文件中,因此,如果应用程序退出,则cookie始终存在,除非显式调用delete。

有关cookie_jar的更多详细信息,请参见:https://github.com/flutterchina/cookie_jar

答案 1 :(得分:0)

检查csrftoken是否需要在标头和cookie中传递,或者仅在其中之一中传递。有时需要将其作为标头包括在内,如下面的示例所示,但是标头名称有所不同。要保留cookie,请使用PersistCookieJar。其他选项通过BaseOptions(以前称为Options)保留。

将这些插件的latest versions添加到pubspec.yaml

  path_provider: ^1.1.0
  dio: ^2.1.6
  cookie_jar: ^1.0.0

在名为webFunctions的新类中:

import 'dart:io';
import 'package:cookie_jar/cookie_jar.dart';
import 'package:dio/dio.dart';
import 'package:path_provider/path_provider.dart';

class webFunctions {
  final Dio _dio = Dio();
  PersistCookieJar persistentCookies;
  final String URL = "http://test/";

  Future<String> get _localPath async {
    final directory = await getApplicationDocumentsDirectory();
    return directory.path;
  }

  Future<Directory> get _localCoookieDirectory async {
    final path = await _localPath;
    final Directory dir = new Directory('$path/cookies');
    await dir.create();
    return dir;
  }

  Future<String> getCsrftoken() async{
    try {
      String csrfTokenValue;
      final Directory dir = await _localCoookieDirectory;
      final cookiePath = dir.path;
      persistentCookies = new PersistCookieJar(dir: '$cookiePath');
      persistentCookies.deleteAll(); //clearing any existing cookies for a fresh start
      _dio.interceptors.add(
          CookieManager(persistentCookies) //this sets up _dio to persist cookies throughout subsequent requests
      );
      _dio.options = new BaseOptions(
        baseUrl: URL,
        contentType: ContentType.json,
        responseType: ResponseType.plain,
        connectTimeout: 5000,
        receiveTimeout: 100000,
        headers: {
          HttpHeaders.userAgentHeader: "dio",
          "Connection": "keep-alive",
        },
      ); //BaseOptions will be persisted throughout subsequent requests made with _dio
      _dio.interceptors.add(
          InterceptorsWrapper(
              onResponse:(Response response) {
                List<Cookie> cookies = persistentCookies.loadForRequest(Uri.parse(URL));
                csrfTokenValue = cookies.firstWhere((c) => c.name == 'csrftoken', orElse: () => null)?.value;
                if (csrfTokenValue != null) {
                  _dio.options.headers['X-CSRF-TOKEN'] = csrfTokenValue; //setting the csrftoken from the response in the headers
                }
                return response;
              }
          )
      );
      await _dio.get("/accounts/login/");
      return csrfTokenValue;
    } catch (error, stacktrace) {
      print("Exception occured: $error stackTrace: $stacktrace");
      return null;
    }
  }

  getSessionId() async {
    try {
      final csrf = await getCsrftoken();
      FormData formData = new FormData.from({
        "username": "username",
        "password": 'A *passphrase* is stronger than a password.',
        "csrfmiddlewaretoken" : '$csrf'
      });
      Options optionData = new Options(
        contentType: ContentType.parse("application/x-www-form-urlencoded"),
      );
      Response response = await _dio.post("/accounts/login/", data: formData, options: optionData);
      print(response.statusCode);
    } on DioError catch(e) {
      if(e.response != null) {
        print( e.response.statusCode.toString() + " " + e.response.statusMessage);
        print(e.response.data);
        print(e.response.headers);
        print(e.response.request);
      } else{
        print(e.request);
        print(e.message);
      }
    }
    catch (error, stacktrace) {
      print("Exception occured: $error stackTrace: $stacktrace");
      return null;
    }
  }
}