Here's a refined version of your document, including a background section and the workflow for Firebase Authentication. I've also added a section on how to retrieve all users from Firebase Authentication.


Firebase Authentication

背景

在现代应用中,用户身份验证是确保系统安全性的重要环节。Firebase Authentication 提供了简单易用的身份验证服务,支持多种身份验证方法,包括电子邮件密码登录、第三方登录(如 Google、Facebook)、匿名登录等。为了确保操作的安全性,如文件上传,通常需要验证用户的身份,并验证其所携带的 Token 是否有效。

在本指南中,我们将展示如何使用 Firebase Authentication 验证用户的 Token,并将其集成到一个 Java 应用程序中,以确保只有经过身份验证的用户才能执行敏感操作。

验证 Token

在 Firebase 中,我们可以使用 FirebaseAuth 类来验证用户的 Token。以下示例展示了如何在 Java 中进行 Token 验证:

简单的验证示例

以下是一个简单的测试示例,用于验证 Token 的有效性:

import java.io.IOException;

import org.junit.Before;
import org.junit.Test;

import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseToken;
import com.litongjava.tio.utils.environment.EnvUtils;

public class FirebaseVerifyTokenTest {

  @Before
  public void before() {
    EnvUtils.load();
    try {
      new FirebaseAppConfiguration().config();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  @Test
  public void verify() {
    String idToken = "YOUR_ID_TOKEN_HERE";
    try {
      FirebaseToken decodedToken = FirebaseAuth.getInstance().verifyIdToken(idToken);
      String uid = decodedToken.getUid();
      System.out.println("Token is valid. User ID: " + uid);
    } catch (Exception e) {
      e.printStackTrace();
      System.out.println("Token is invalid: " + e.getMessage());
    }
  }
}

在这个示例中,我们使用 FirebaseAuth.getInstance().verifyIdToken(idToken) 方法来验证用户的 Token。如果 Token 有效,我们可以获取用户的 UID,并允许用户执行接下来的操作。

使用拦截器验证 Token

为了在实际应用中集成 Token 验证,我们可以创建一个拦截器来自动验证请求中的 Token。以下是实现方法:

package com.litongjava.open.chat.interceptor;

import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseToken;
import com.jfinal.kit.StrKit;
import com.litongjava.tio.boot.http.TioHttpContext;
import com.litongjava.tio.http.common.HttpRequest;
import com.litongjava.tio.http.common.HttpResponse;
import com.litongjava.tio.http.common.HttpResponseStatus;
import com.litongjava.tio.http.common.RequestLine;
import com.litongjava.tio.http.server.intf.HttpRequestInterceptor;
import com.litongjava.tio.utils.resp.RespVo;

public class AuthInterceptor implements HttpRequestInterceptor {

  @Override
  public HttpResponse doBeforeHandler(HttpRequest request, RequestLine requestLine, HttpResponse responseFromCache) {
    String authorization = request.getHeader("authorization");

    if (StrKit.isBlank(authorization)) {
      return fail("Authorization header cannot be empty");
    }
    String[] split = authorization.split(" ");
    if (split.length < 2) {
      return fail("Failed to extract token");
    }
    String idToken = split[1];
    try {
      FirebaseToken decodedToken = FirebaseAuth.getInstance().verifyIdToken(idToken);
      String uid = decodedToken.getUid();
      TioHttpContext.setUserId(uid);
    } catch (Exception e) {
      return fail("Failed to validate token: " + e.getMessage());
    }
    return null;
  }

  private HttpResponse fail(String msg) {
    HttpResponse response = TioHttpContext.getResponse();
    response.setStatus(HttpResponseStatus.C401);
    response.setJson(RespVo.fail(msg));
    return response;
  }

  @Override
  public void doAfterHandler(HttpRequest request, RequestLine requestLine, HttpResponse response, long cost) {
    // Implement if needed
  }
}

配置拦截器

将拦截器配置到服务器中,确保它能够拦截所有需要验证的请求:

import com.litongjava.open.chat.interceptor.AuthInterceptor;
import com.litongjava.tio.boot.http.interceptor.HttpServerInterceptorModel;
import com.litongjava.tio.boot.http.interceptor.ServerInteceptorConfigure;
import com.litongjava.tio.boot.server.TioBootServer;
import com.litongjava.tio.http.server.intf.HttpRequestInterceptor;

public class InterceptorConfiguration {

  public void config() {
    HttpRequestInterceptor authTokenInterceptor = new AuthInterceptor();
    HttpServerInterceptorModel model = new HttpServerInterceptorModel();
    model.setInterceptor(authTokenInterceptor);
    model.addBlockedUrl("/**"); // 拦截所有路由
    model.addAllowedUrls("", "/"); // 允许的路由

    ServerInteceptorConfigure serverInteceptorConfigure = new ServerInteceptorConfigure();
    serverInteceptorConfigure.add(model);
    TioBootServer.me().setServerInteceptorConfigure(serverInteceptorConfigure);
  }
}

通过以上配置,我们确保每个请求都会经过 Token 验证,只有在验证通过的情况下才会继续处理请求。

用户操作

获取 Firebase Authentication 上的所有用户

要从 Firebase Authentication 中获取所有用户,可以使用 Firebase Admin SDK。以下是一个 Java 示例,展示如何分页检索所有用户:

package com.litongjava.firebase;

import java.io.IOException;

import org.junit.Test;

import com.google.firebase.auth.ExportedUserRecord;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseAuthException;
import com.google.firebase.auth.ListUsersPage;
import com.litongjava.open.chat.config.FirebaseAppConfiguration;
import com.litongjava.tio.utils.environment.EnvUtils;

public class FirebaseUsers {

  @Test
  public void listUser() {

    EnvUtils.load();
    try {
      new FirebaseAppConfiguration().config();
    } catch (IOException e) {
      e.printStackTrace();
      return;
    }

    ListUsersPage page = null;

    try {
      page = FirebaseAuth.getInstance().listUsers(null);
    } catch (FirebaseAuthException e) {
      e.printStackTrace();
      return;
    }
    while (page != null) {
      for (ExportedUserRecord user : page.getValues()) {
        System.out.println("User: " + user.getUid());
      }
      page = page.getNextPage();
    }
  }

}

这个代码段将遍历并打印出所有 Firebase Authentication 中的用户 UID。此操作对于管理用户、统计分析或执行批量操作非常有用。