You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter实现指定邮箱密码登录的Firebase管理员页面

Flutter固定管理员账号+用户数据查看页实现方案

前置操作:创建固定管理员账号

  • 打开Firebase项目控制台,进入「Authentication」-「Users」页面,点击添加用户
  • 输入你预先设定的管理员固定邮箱、密码,保存好这组凭证,该账号为唯一管理员,不开放注册入口。

步骤1:修复并改造登录页逻辑

你原有登录代码存在逻辑问题:没有等待登录接口返回就直接跳转页面,也没有做身份区分,按以下代码修改即可:

  1. 首先在MyLogin类里定义固定管理员邮箱常量,替换为你刚才创建的管理员邮箱:
const String kAdminEmail = "admin@your-app.com";
  1. 替换原有SignIn方法,增加异常捕获和身份判断逻辑:
Future SignIn() async {
  try {
    UserCredential credential = await FirebaseAuth.instance.signInWithEmailAndPassword(
      email: emailController.text.trim(),
      password: passwordController.text.trim()
    );
    if (credential.user == null) return;
    setState(() {
      _success = 2;
      _userEmail = credential.user!.email ?? "";
    });
    // 按身份跳转对应页面
    if (credential.user!.email == kAdminEmail) {
      Navigator.pushReplacement(
        context,
        MaterialPageRoute(builder: (context) => const AdminDashboard())
      );
    } else {
      Navigator.pushReplacement(
        context,
        MaterialPageRoute(builder: (context) => const Imageslider())
      );
    }
  } on FirebaseAuthException catch (e) {
    setState(() {
      _success = 3;
    });
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text("登录失败:${e.message ?? "请检查账号密码"}"))
    );
  }
}
  1. 修改登录按钮的点击事件,移除原有直接写的跳转逻辑,增加基础非空校验:
onPressed: () {
  if (emailController.text.trim().isEmpty || passwordController.text.trim().isEmpty) {
    ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(content: Text("请输入邮箱和密码"))
    );
    return;
  }
  SignIn();
},

步骤2:新建管理员数据展示页

在lib目录下新建admin_dashboard.dart文件,写入以下代码,页面会自动拉取Firestore中users集合的所有用户数据展示,同时带退出登录功能:

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'login.dart';

class AdminDashboard extends StatefulWidget {
  const AdminDashboard({Key? key}) : super(key: key);

  @override
  State<AdminDashboard> createState() => _AdminDashboardState();
}

class _AdminDashboardState extends State<AdminDashboard> {
  final String kAdminEmail = "admin@your-app.com";

  @override
  void initState() {
    super.initState();
    // 进页面先校验权限,非管理员直接踢回登录页
    User? currentUser = FirebaseAuth.instance.currentUser;
    if (currentUser == null || currentUser.email != kAdminEmail) {
      Future.microtask(() {
        Navigator.pushReplacement(
          context,
          MaterialPageRoute(builder: (context) => const MyLogin())
        );
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("管理员后台 - 用户列表"),
        backgroundColor: Colors.black87,
        actions: [
          IconButton(
            onPressed: () async {
              await FirebaseAuth.instance.signOut();
              Navigator.pushReplacement(
                context,
                MaterialPageRoute(builder: (context) => const MyLogin())
              );
            },
            icon: const Icon(Icons.logout)
          )
        ],
      ),
      body: StreamBuilder<QuerySnapshot>(
        stream: FirebaseFirestore.instance.collection('users').snapshots(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return const Center(child: CircularProgressIndicator());
          }
          if (snapshot.hasError) {
            return Center(child: Text("加载失败:${snapshot.error}"));
          }
          if (!snapshot.hasData || snapshot.data!.docs.isEmpty) {
            return const Center(child: Text("暂无注册用户数据"));
          }
          return ListView.builder(
            padding: const EdgeInsets.all(16),
            itemCount: snapshot.data!.docs.length,
            itemBuilder: (context, index) {
              final userData = snapshot.data!.docs[index].data() as Map<String, dynamic>;
              return Card(
                elevation: 2,
                margin: const EdgeInsets.only(bottom: 12),
                child: ListTile(
                  leading: const CircleAvatar(child: Icon(Icons.person)),
                  title: Text(userData['name'] ?? "未填写昵称"),
                  subtitle: Text(userData['email'] ?? "无邮箱记录"),
                  trailing: Text(
                    "UID: ${userData['uid'].toString().substring(0,8)}...",
                    style: const TextStyle(fontSize: 12, color: Colors.grey),
                  ),
                ),
              );
            },
          );
        },
      ),
    );
  }
}

步骤3:修复原有注册页逻辑bug

你原有注册页的成功/失败判断写反了,找到注册按钮的then回调部分,替换为以下代码:

_register(name.text, emailController.text, passwordController.text).then((user) {
  setState(() {
    isLoading = false;
  });
  if (user != null) {
    ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(content: Text("注册成功,请登录"))
    );
    Navigator.pushReplacement(
      context, MaterialPageRoute(builder: (_) => MyLogin())
    );
  } else {
    ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(content: Text("注册失败,请检查邮箱格式或密码长度(需≥6位)"))
    );
  }
});

补充说明

  • 不要把管理员密码硬编码在客户端代码中,管理员账号直接在Firebase后台创建即可,客户端仅比对邮箱做身份识别,不存在密码泄露风险。
  • 上线前建议在Firestore安全规则中增加限制,仅允许管理员邮箱账号读取users集合全量数据,避免普通用户越权访问。
  • 记得在登录页文件顶部引入新建的管理员页:import 'admin_dashboard.dart';

内容的提问来源于stack exchange,提问作者QueenBee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 21:30:42