使用 Firebase Admin SDK 进行匿名用户管理与自定义状态标记
在现代应用程序中,匿名用户管理是一个常见的需求,尤其是在需要为未登录用户提供部分功能的场景中。通过 Firebase Admin SDK,开发者可以方便地管理匿名用户,并为用户设置自定义的状态标记,例如记录用户是否使用过某项特定功能。
本文将介绍如何使用 Firebase Admin SDK 实现匿名用户的管理,并通过自定义声明(Custom Claims)来标记用户是否使用过 AI 问答功能。我们将结合一个实际的代码示例来展示如何实现这一功能。
一、匿名用户与 getProviderData()
方法
在 Firebase 中,用户可以通过多种身份验证方式登录,如电子邮件和密码、Google、Facebook 等。当用户未通过任何提供程序登录时,他们被视为匿名用户。判断用户是否为匿名用户的关键在于 getProviderData()
方法。
1.1 getProviderData()
方法
getProviderData()
方法返回的是与用户关联的身份验证提供程序的数据列表。每个身份验证提供程序(如 Google、Facebook)对应一个 UserInfo
对象。这个方法返回一个 UserInfo[]
数组,其中每个 UserInfo
对象包含以下信息:
getProviderId()
: 返回身份提供程序的唯一标识符。getUid()
: 返回与该提供程序关联的用户标识符。getDisplayName()
: 返回用户的显示名称。getPhotoUrl()
: 返回用户的头像 URL。getEmail()
: 返回用户的电子邮件地址。getPhoneNumber()
: 返回用户的电话号码。
1.2 区分匿名用户
匿名用户通常没有绑定任何身份验证提供程序,因此 getProviderData()
通常返回一个空数组或仅包含默认的 Firebase 提供程序。通过检查 getProviderData()
的长度,我们可以判断用户是否为匿名用户:
public boolean isAnonymous(UserRecord userRecord) {
UserInfo[] providerData = userRecord.getProviderData();
return providerData.length < 1;
}
在这个方法中,如果 providerData
的长度小于 1,那么该用户就是匿名用户。
二、自定义声明与状态标记
Firebase 提供了自定义声明(Custom Claims)功能,允许开发者为用户设置自定义的元数据。在我们的场景中,可以利用这一功能来记录用户是否使用过 AI 问答。
2.1 更新用户状态
通过 UserRecord.UpdateRequest
,我们可以为用户设置自定义声明。在以下代码中,我们将自定义声明 usedAIQuestioning
设置为 true
,表示用户已经使用过 AI 问答功能:
public void updateUsing(String uid) {
FirebaseAuth auth = FirebaseAuth.getInstance();
UserRecord.UpdateRequest request = new UserRecord.UpdateRequest(uid)
.setCustomClaims(Collections.singletonMap("usedAIQuestioning", true));
try {
auth.updateUser(request);
} catch (FirebaseAuthException e) {
e.printStackTrace();
}
}
2.2 检查用户状态
要检查用户是否使用过 AI 问答功能,可以通过读取用户的自定义声明来判断:
public boolean isUsing(UserRecord userRecord) {
Map<String, Object> customClaims = userRecord.getCustomClaims();
return customClaims.get("usedAIQuestioning") != null && (boolean) customClaims.get("usedAIQuestioning");
}
在这个方法中,我们通过读取 customClaims
来判断 usedAIQuestioning
是否存在以及是否为 true
,以此来确定用户是否已经使用过 AI 问答功能。
三、综合应用
以下是一个综合应用示例,展示了如何结合匿名用户的判断与自定义状态标记,来管理用户的访问权限:
import java.util.Collections;
import java.util.Map;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseAuthException;
import com.google.firebase.auth.UserInfo;
import com.google.firebase.auth.UserRecord;
public class FirebaseUserService {
private String usedKey = "usedAIQuestioning";
public void updateUsing(String uid) {
FirebaseAuth auth = FirebaseAuth.getInstance();
UserRecord.UpdateRequest request = new UserRecord.UpdateRequest(uid).setCustomClaims(Collections.singletonMap(usedKey, true));
try {
auth.updateUser(request);
} catch (FirebaseAuthException e) {
e.printStackTrace();
}
}
public boolean isUsing(UserRecord userRecord) {
Map<String, Object> customClaims = userRecord.getCustomClaims();
return customClaims.get(usedKey) != null && (boolean) customClaims.get(usedKey);
}
public UserRecord getUser(String uid) {
FirebaseAuth auth = FirebaseAuth.getInstance();
UserRecord userRecord = null;
try {
userRecord = auth.getUser(uid);
} catch (FirebaseAuthException e) {
e.printStackTrace();
return null;
}
return userRecord;
}
public boolean isAnonymous(UserRecord userRecord) {
UserInfo[] providerData = userRecord.getProviderData();
if (providerData.length < 1) {
return true;
}
return false;
}
}
public void handleUser(String userId) {
boolean isAdmin = "0".equals(userId);
UserRecord userRecord = null;
if (!isAdmin) {
FirebaseUserService firebaseUserService = Aop.get(FirebaseUserService.class);
userRecord = firebaseUserService.getUser(userId);
boolean isAnonymous = firebaseUserService.isAnonymous(userRecord);
if (isAnonymous) {
boolean used = firebaseUserService.isUsing(userRecord);
if (used) {
// 需要用户登录
SsePacket ssePacket = new SsePacket(AiChatEventName.need_login, ("").getBytes());
Tio.send(channelContext, ssePacket);
closeSeeConnection(channelContext);
return RespBodyVo.fail("need login");
} else {
firebaseUserService.updateUsing(userId);
}
}
}
//....
}
在这个方法中,首先判断用户是否为管理员(admin)。如果用户不是管理员,程序会进一步判断用户是否为匿名用户,以及是否已经使用过 AI 问答功能。如果用户是匿名用户且已经使用过 AI 问答功能,则要求用户登录;否则,更新用户的状态为已使用 AI 问答功能。程序并不会终止,并且会继续向下运行. 下次再调用该方法时 used 为 true 会系统用户登录
四、总结
通过本文的示例,我们展示了如何使用 Firebase Admin SDK 来管理匿名用户,并通过自定义声明来记录用户的特定状态。这一功能在为用户提供定制化体验时尤为有用。通过合理利用这些工具,开发者可以更好地管理用户数据,并根据用户的状态提供个性化的服务。