はじめに
自前で作成したバックエンドの認証機能をRest APIで呼び出して、その認証情報をFlutterでどうやって利用するかを考えた時に、クッキー(Cookies)を利用しようとなったので、FlutterではCookiesはどうやったら実装できるのか調べました
FlutterでのCookieの利用方法についてのナレッジを記載していきます
Cookie初歩形
まずFlutterでCookiesを利用したい場合はデフォルトクッキーが備わっています
Cookie利用の初歩形
import 'dart:io';
Cookie cookie = Cookie('name', 'value')
しかしこれだけではただのマップ型のインスタンス感があり、実用としては使いづらいです
外部パッケージ導入
通常Cookiieを使用したい場合はAPIを利用する場面であるので、中国製のDioというHttpClientのパッケージを利用します
また、DioとCookieをいい感じで利用できるようにしてくれるパッケージCookieJarやCookieManagerもインストールします
pubspec.yaml
dependencies:
dio: ^4.0.4
cookie_jar: ^3.0.1
dio_cookie_manager: ^2.0.0
path_provider: ^2.0.9
path_providerはdio_cookie_managerの説明書きにクッキーを永続化するなら入れろと書かれていました
永続化する場合はどうやらストレージにCookieを保管するためにパーミッションの設定が必要なようです
デフォルトでは読み取り専用になっているので書き込みもできるように設定が必要な模様
Cookie基本形その1
HttpClientのDioを利用したCookieの使い方としては以下の形が基本形その1となります
import 'dart:io';
import 'package:cookie_jar/cookie_jar.dart';
import 'package:dio/dio.dart';
import 'package:dio_cookie_manager/dio_cookie_manager.dart';
final Uri _uriHost = Uri.parse('ホスト');
Future auth() async {
Dio dio = Dio();
List<Cookie> cookies = [];
dio.options.baseUrl = _uriHost.toString();
dio.options.connectTimeout = 5000;
dio.options.receiveTimeout = 3000;
dio.options.contentType = 'application/json';
try {
CookieJar cookieJar = CookieJar();
cookieJar.saveFromResponse(_uriHost, _cookies);
dio.interceptors.add(CookieManager(cookieJar));
final response = await dio.post(
'/authen/jwt/create',
data: {
'email': email,
'password': password,
}
);
cookies = [ ..._cookies, Cookie('access_token', response.data['access']) ];
List<Cookie> result = await cookieJar.loadForRequest(_uriHost);
print(result);
} catch(error) {
message = '正しいEメールとパスワードを入力してください';
print(error);
}
}
Cookie永続化
上の基本形のクッキーは永続的なインスタンスではないので、Cookiesをほかのメソッドやクラスからなどでも使いたいときはPersistCookieJarを使う
こちらがCookieを一番使うことを最も想定された使い方だと思います
認証情報をCookieへ格納して永続化する基本形
login.dart
import 'dart:io';
import 'package:cookie_jar/cookie_jar.dart';
import 'package:dio/dio.dart';
import 'package:dio_cookie_manager/dio_cookie_manager.dart';
import 'package:path_provider/path_provider.dart';
final Uri _uriHost = Uri.parse('http://ホスト'); // http://10.0.2.2:8000
Future auth() async {
Dio dio = Dio();
List<Cookie> cookies = [];
dio.options.baseUrl = _uriHost.toString();
dio.options.connectTimeout = 5000;
dio.options.receiveTimeout = 3000;
dio.options.contentType = 'application/json';
try {
Directory appDocDir = await getApplicationDocumentsDirectory();
String appDocPath = appDocDir.path;
PersistCookieJar cookieJar = PersistCookieJar(storage: FileStorage(appDocPath+"/.cookies/"));
cookieJar.saveFromResponse(_uriHost, cookies);
dio.interceptors.add(CookieManager(cookieJar));
final response = await dio.post(
'/authen/jwt/create',
data: {
'email': userModel.email,
'password': password,
}
);
cookies = [ ...cookies, Cookie('access_token', response.data['access']) ];
cookieJar.saveFromResponse(_uriHost, cookies);
List<Cookie> cookieList = await cookieJar.loadForRequest(_uriHost); // 格納されたクッキーを確認しているだけの処理
print(cookieList);
} catch(error) {
message = '正しいEメールとパスワードを入力してください';
print(error);
}
}
ここで格納されたクッキーのインスタンスは以下のようにするとほかのメソッドやクラスなどから参照できるようになる
これにより一度ログインしたときの認証情報を他のクラスで共有することができて、Cookieを便利に使えるようになった
永続化したCookie情報を他のメソッドやクラスなどから読み込む方法
上記で格納したCookie上に格納されている認証情報は以下のようにして取り出して利用することができる
例: fetch.dart
import 'dart:io';
import 'package:cookie_jar/cookie_jar.dart';
import 'package:dio/dio.dart';
import 'package:dio_cookie_manager/dio_cookie_manager.dart';
import 'package:path_provider/path_provider.dart';
final Uri _uriHost = Uri.parse('ホスト'); // http://10.0.2.2:8000
Future fetch() async {
final Dio dio = Dio();
Directory appDocDir = await getApplicationDocumentsDirectory();
String appDocPath = appDocDir.path;
PersistCookieJar cookieJar = PersistCookieJar(storage: FileStorage(appDocPath+"/.cookies/"));
dio.interceptors.add(CookieManager(cookieJar));
print(await cookieJar.loadForRequest(_uriHost));
// TODO fetchの処理
final response = await dio.get(
'/list-data',
// Cookiesの認証情報をHeaderに持たせるetc........
// options: Options(
// headers: {
// 'Authorization': 'JWT ${cookieList.first.value}',
// },
// ),
);
}