Post request with Cookies in Flutter

12,183

Solution 1

From the Dio Dart API Docs:

Cookie Manager

You can manage the request/response cookies using cookieJar .

The dio cookie manage API is based on the withdrawn cookie_jar.

You can create a CookieJar or PersistCookieJar to manage cookies automatically, and dio use the CookieJar by default, which saves the cookies in RAM. If you want to persists cookies, you can use the PersistCookieJar class, the example codes as follows:

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

PersistCookieJar is a cookie manager which implements the standard cookie policy declared in RFC. PersistCookieJar persists the cookies in files, so if the application exit, the cookies always exist unless call delete explicitly.

More details about cookie_jar see : https://github.com/flutterchina/cookie_jar .

Solution 2

Check if the csrftoken needs to be passed in the header and the cookie or just one of them. It sometimes needs to be included as a header, which is shown in the example below, but the header name varies. To persist cookies, use a PersistCookieJar. Other options are persisted through BaseOptions (previously named Options).

Add to pubspec.yaml the latest versions of these plugins

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

In a new class named 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;
    }
  }
}
Share:
12,183
Dev9977
Author by

Dev9977

Updated on December 07, 2022

Comments

  • Dev9977
    Dev9977 over 1 year

    I'm trying to add Cookies to my request:

    Here i get csrftoken with a GET request:

     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;
        }
    

    Here i'm trying to perform the POST (application/x-www-form-urlencoded) request using the package Dio.

    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);
    }
    

    I get 403 status code, because i need to add as a cookie csrftoken.

    How should I proceed?