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

Flutter集成Firebase:整数值的存储与读取及自定义学号登录的存储方案技术咨询

针对你的两个问题,我来逐一给出实用的解决方案:

问题1:如何在Flutter中将整数值保存到Firebase,并读取已保存的该整数值?

Firebase提供了Cloud Firestore和Realtime Database两种常用数据库方案,我会分别给出实现代码:

Cloud Firestore 实现

保存整数值

先确保项目已集成cloud_firestore依赖,然后通过以下代码完成保存:

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';

Future<void> saveStudentId(int studentId) async {
  try {
    // 登录后通过Firebase Auth获取当前用户UID,作为文档ID确保唯一性
    String userId = FirebaseAuth.instance.currentUser!.uid;
    await FirebaseFirestore.instance
        .collection('users')
        .doc(userId)
        .set({'studentId': studentId}, SetOptions(merge: true));
    print("学号已成功保存");
  } catch (e) {
    print("保存失败: $e");
    // 可根据业务需求添加弹窗提示等错误处理逻辑
  }
}

读取整数值

Future<int?> getStudentId() async {
  try {
    String userId = FirebaseAuth.instance.currentUser!.uid;
    DocumentSnapshot userDoc = await FirebaseFirestore.instance
        .collection('users')
        .doc(userId)
        .get();
    
    if (userDoc.exists) {
      // 注意将Firestore返回的动态类型转为int
      return userDoc['studentId'] as int?;
    } else {
      print("用户数据不存在");
      return null;
    }
  } catch (e) {
    print("读取失败: $e");
    return null;
  }
}

Realtime Database 实现

如果使用Realtime Database,先集成firebase_database依赖:

保存整数值

import 'package:firebase_database/firebase_database.dart';
import 'package:firebase_auth/firebase_auth.dart';

Future<void> saveStudentIdToRealtimeDb(int studentId) async {
  try {
    String userId = FirebaseAuth.instance.currentUser!.uid;
    await FirebaseDatabase.instance
        .ref('users/$userId/studentId')
        .set(studentId);
    print("学号已成功保存");
  } catch (e) {
    print("保存失败: $e");
  }
}

读取整数值

Future<int?> getStudentIdFromRealtimeDb() async {
  try {
    String userId = FirebaseAuth.instance.currentUser!.uid;
    DatabaseEvent event = await FirebaseDatabase.instance
        .ref('users/$userId/studentId')
        .once();
    // 转换类型时需注意Realtime Database返回的动态类型
    return event.snapshot.value as int?;
  } catch (e) {
    print("读取失败: $e");
    return null;
  }
}

问题2:使用学号(整数)和密码登录,Firebase Auth无此类表单,该整数值应存储在何处?

你说得没错,Firebase Auth默认没有直接的「学号+密码」登录方式,但我们可以通过Firebase Auth + 数据库存储自定义字段的组合方案实现,推荐两种实用思路:

方案1:结合Firebase Auth邮箱/密码登录 + Firestore存储学号

核心逻辑:用学号生成唯一占位邮箱(或让用户绑定真实邮箱),将学号作为用户自定义字段存入Firestore;登录时先通过学号找到对应邮箱,再用邮箱密码完成Auth登录。

注册流程示例

import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:bcrypt/bcrypt.dart'; // 用于密码哈希,避免明文存储

Future<UserCredential> registerWithStudentId(int studentId, String password) async {
  // 用学号生成唯一占位邮箱,避免重复注册
  String placeholderEmail = "$studentId@yourschoolapp.com";
  // 哈希密码后存储
  String hashedPassword = BCrypt.hashpw(password, BCrypt.gensalt());
  
  try {
    // 创建Firebase Auth用户
    UserCredential userCred = await FirebaseAuth.instance.createUserWithEmailAndPassword(
      email: placeholderEmail,
      password: password,
    );
    
    // 将学号、哈希密码等信息存入Firestore,关联用户UID
    await FirebaseFirestore.instance
        .collection('users')
        .doc(userCred.user!.uid)
        .set({
          'studentId': studentId,
          'email': placeholderEmail,
          'hashedPassword': hashedPassword
        });
    
    // 建议在Firebase控制台给studentId字段添加唯一索引,防止重复注册
    return userCred;
  } catch (e) {
    print("注册失败: $e");
    rethrow;
  }
}

登录流程示例

Future<UserCredential> loginWithStudentId(int studentId, String password) async {
  try {
    // 通过学号在Firestore中查找对应用户
    QuerySnapshot query = await FirebaseFirestore.instance
        .collection('users')
        .where('studentId', isEqualTo: studentId)
        .limit(1)
        .get();
    
    if (query.docs.isEmpty) {
      throw Exception("未找到该学号对应的用户");
    }
    
    // 获取用户的占位邮箱和哈希密码
    String email = query.docs.first['email'] as String;
    String hashedPassword = query.docs.first['hashedPassword'] as String;
    
    // 验证密码是否匹配
    if (!BCrypt.checkpw(password, hashedPassword)) {
      throw Exception("密码错误");
    }
    
    // 用邮箱和密码完成Firebase Auth登录
    return await FirebaseAuth.instance.signInWithEmailAndPassword(
      email: email,
      password: password,
    );
  } catch (e) {
    print("登录失败: $e");
    rethrow;
  }
}

方案2:使用Firebase自定义令牌(适合无邮箱场景)

如果不想依赖邮箱,可以通过自定义令牌实现:后端(或Cloud Functions)验证学号和密码的合法性,生成自定义令牌后,前端用令牌完成Auth登录。

Cloud Functions 后端验证示例(Node.js)

const functions = require("firebase-functions");
const admin = require("firebase-admin");
const bcrypt = require("bcrypt");
admin.initializeApp();

exports.loginWithStudentId = functions.https.onCall(async (data) => {
  const { studentId, password } = data;
  
  // 查找学号对应的用户
  const userQuery = await admin.firestore()
    .collection('users')
    .where('studentId', '==', studentId)
    .limit(1)
    .get();
  
  if (userQuery.empty) {
    throw new functions.https.HttpsError("not-found", "用户不存在");
  }
  
  const userDoc = userQuery.docs[0];
  const userData = userDoc.data();
  
  // 验证密码(注册时已存储哈希值)
  const isPasswordValid = await bcrypt.compare(password, userData.hashedPassword);
  if (!isPasswordValid) {
    throw new functions.https.HttpsError("unauthenticated", "密码错误");
  }
  
  // 生成自定义令牌,以用户UID为标识
  const customToken = await admin.auth().createCustomToken(userDoc.id);
  return { token: customToken };
});

Flutter 前端调用示例

import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_functions/firebase_functions.dart';

Future<UserCredential> loginWithCustomToken(int studentId, String password) async {
  try {
    HttpsCallable callable = FirebaseFunctions.instance.httpsCallable('loginWithStudentId');
    final result = await callable.call({
      'studentId': studentId,
      'password': password,
    });
    
    String customToken = result.data['token'];
    return await FirebaseAuth.instance.signInWithCustomToken(customToken);
  } catch (e) {
    print("登录失败: $e");
    rethrow;
  }
}

关键注意事项

  • 密码安全:绝对禁止明文存储密码,必须使用bcrypt等哈希算法处理后再存入数据库。
  • 学号唯一性:在Firestore中给studentId字段配置唯一索引,防止同一学号重复注册。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 21:17:49