はじめに
前回(Part 2)では、RBACを支えるデータベース設計とER図を紹介しました。
今回はその実データを用いて、Flutterアプリ内でのページアクセス・ボタン表示の制御方法を解説します。
使用するのは:
- ルーティング:
go_router
- 状態管理:
Riverpod
前提:ログイン後に権限コード一覧を取得
まず、ログイン時に後端から取得する権限リストを前提とします:
["user:view", "user:edit", "order:view", "report:export"]
Riverpodでの権限管理Provider
final userPermissionsProvider = Provider<List<String>>((ref) {
// 実際には SecureStorage や API から取得
return [
'user:view',
'user:edit',
'order:view',
'report:export',
];
});
ページアクセス制御(go_routerのpageBuilder)
GoRoute(
path: '/users',
builder: (context, state) {
final permissions = ref.watch(userPermissionsProvider);
return permissions.contains('user:view')
? const UserPage()
: const ForbiddenPage(); // アクセス拒否ページ
},
),
このようにルート単位で制御が可能です。
ボタンの表示/非表示制御
final permissions = ref.watch(userPermissionsProvider);
if (permissions.contains('user:edit'))
ElevatedButton(
onPressed: () => editUser(),
child: const Text('編集'),
);
ユーザーが持たない権限のボタンは表示すらされません。
カスタムWidget化して再利用
class PermissionButton extends ConsumerWidget {
final String permissionCode;
final VoidCallback onPressed;
final Widget child;
const PermissionButton({
required this.permissionCode,
required this.onPressed,
required this.child,
});
@override
Widget build(BuildContext context, WidgetRef ref) {
final permissions = ref.watch(userPermissionsProvider);
if (!permissions.contains(permissionCode)) return const SizedBox.shrink();
return ElevatedButton(onPressed: onPressed, child: child);
}
}
使い方:
PermissionButton(
permissionCode: 'user:delete',
onPressed: deleteUser,
child: const Text('削除'),
),
よくある質問
Q1. 複数の権限で許可したい場合?
final allow = permissions.any((p) => ['user:edit', 'admin'].contains(p));
Q2. 権限がないけど「ボタンは表示」だけしたい?
if (permissions.contains('user:delete')) {
ElevatedButton(onPressed: deleteUser, child: Text("削除"));
} else {
ElevatedButton(onPressed: null, child: Text("削除")); // 無効化
}
設計のベストプラクティス
項目 | 推奨実装 |
---|---|
権限コードの一元管理 | enumまたはConst管理 |
ページ遷移前の判定 | go_routerのpageBuilderで行う |
再利用性のあるWidget | PermissionButtonなどで共通化 |
セキュリティ注意点
前回と重複しますが、改めて重要なポイント:
「ボタンを隠すこと」と「操作を防ぐこと」は別。APIは常に後端で検査すること!
シリーズリスト
Flutterで作る安全な権限制御【Part 1】業界標準と設計指針のすべて
Flutterで作る安全な権限制御【Part 2】RBACを支えるデータベース設計とER図(Mermaid付き)
Flutterで作る安全な権限制御【Part 3】ページとボタンを権限で制御する実装編(go_router × Riverpod)
Flutterで作る安全な権限制御【Part 4】Flutterアプリの反編譯リスクとセキュリティ対策
Security Flutter obfuscation