【Flutter】機密データを読み書きする【flutter_secure_storage】

ネコニウム研究所

PCを利用したモノづくりに関連する情報や超個人的なナレッジを掲載するブログ

【Flutter】機密データを読み書きする【flutter_secure_storage】

2024-5-8 | ,

Flutterのパッケージflutter_secure_storageを使ってパスワードなどの機密データを読み書きしたい!

概要

今回の記事では、Flutterのパッケージflutter_secure_storageを使ってパスワードなどの機密データを読み書きする手順を掲載する。

データの読み書きのフィードバックにトーストを表示するのにパッケージfluttertoastを使ってる。fluttertoastの使い方については下記の記事を参照。

仕様書

環境

  • Android Studio Giraffe | 2023.2.1 Patch 2
  • Flutter 3.19.6
  • fluttertoast: 8.2.5
  • flutter_secure_storage: 9.0.0

手順書

インストール編とコード編の2部構成です。

インストール編

ターミナルでコマンドを実行するか

flutter pub add fluttertoast flutter_secure_storage

pubspec.yamldependencies:に下記のような感じで追加して

dependencies:
  fluttertoast: ^8.2.5
  flutter_secure_storage: ^9.0.0

ターミナルでflutter pub getする。

flutter pub get

コード編

WRITEをタップするとTextFieldの文字列を保存、READをタップすると保存してた文字列をTextFieldに読み込む例。

import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';

void main() {
  runApp(
    MaterialApp(
      home: Scaffold(
        body: const FlutterSecureStorageSample1()
      )
    )
  );
}

void write(String str) async {
  const storage = FlutterSecureStorage();
  await storage.write(key: 'data', value: str);
  Fluttertoast.showToast(
    msg: "Write Data!",
    toastLength: Toast.LENGTH_SHORT,
    gravity: ToastGravity.BOTTOM,
    timeInSecForIosWeb: 1,
    backgroundColor: Colors.pink,
    textColor: Colors.white,
    fontSize: 16.0,
  );
}

Future<String> read() async {
  const storage = FlutterSecureStorage();
  Fluttertoast.showToast(
    msg: "Read Data!",
    toastLength: Toast.LENGTH_SHORT,
    gravity: ToastGravity.BOTTOM,
    timeInSecForIosWeb: 1,
    backgroundColor: Colors.pink,
    textColor: Colors.white,
    fontSize: 16.0,
  );
  return await storage.read(key: 'data') ?? '';
}

class FlutterSecureStorageSample1 extends StatelessWidget {
  FlutterSecureStorageSample1({super.key});

  TextEditingController textEditingController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Center(
        child: SizedBox(
          width: double.infinity,
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
              Padding(
                padding: const EdgeInsets.fromLTRB(16, 16, 16, 16),
                child: TextField(
                  controller: textEditingController,
                  maxLength: 100,
                  decoration: const InputDecoration(hintText: '100文字以内'),
                ),
              ),
              TextButton(
                style: TextButton.styleFrom(
                  backgroundColor: Colors.blue,
                  shape: const RoundedRectangleBorder(
                    borderRadius: BorderRadius.all(Radius.circular(4)),
                  ),
                  padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
                ),
                onPressed: () => write(textEditingController.text),
                child: const Padding(
                  padding: EdgeInsets.fromLTRB(0, 0, 0, 0),
                  child: Text("WRITE",
                      style: TextStyle(fontSize: 16.0, color: Colors.white)),
                ),
              ),
              TextButton(
                style: TextButton.styleFrom(
                  backgroundColor: Colors.blue,
                  shape: const RoundedRectangleBorder(
                    borderRadius: BorderRadius.all(Radius.circular(4)),
                  ),
                  padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
                ),
                onPressed: () => {
                  read().then((result) {
                    textEditingController.text = result;
                  })
                },
                child: const Padding(
                  padding: EdgeInsets.fromLTRB(0, 0, 0, 0),
                  child: Text("READ",
                      style: TextStyle(fontSize: 16.0, color: Colors.white)),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

flutter_secure_storageを使ってデータを書き込むとOSによってそれぞれ下記に保存される。

プラットフォーム
Android KeyStore(アプリケーションデータディレクトリ内の暗号化されたファイル)
iOS Keychain(システムレベルで管理される。ファイルシステム上で直接確認できない)
Linux libsecret (Secret Service API) を使用して暗号化&保存
macOS Keychain(システムレベルで管理される。ファイルシステム上で直接確認できない)
Web LocalStorageorIndexedDB(ブラウザによる。セキュリティ低め)
Windows Data Protection APIを使用して暗号化&保存

まとめ(感想文)

ユーザーに見せたくないデータの保存やパスワードなどの機密データの保存に使えるかもね!

参考文献・引用

下記のサイトを参考にさせていただきました。ありがとうございました。