next-firebase-auth 项目使用示例详解

next-firebase-auth 项目使用示例详解

next-firebase-auth 是一个用于 Next.js 和 Firebase 认证集成的库,它简化了在 Next.js 应用中实现 Firebase 认证的流程。本文将详细介绍该库的各种使用场景和最佳实践。

在 Vercel 中添加 Firebase 认证凭据

将 Firebase 认证凭据作为环境变量添加到 Vercel 有多种方法:

通过 Vercel 控制台添加

  1. 在 Vercel 控制台的环境变量设置中,将认证凭据用双引号包裹后添加
  2. 在 next-firebase-auth 配置中使用该环境变量:
authCredentials: process.env.FIREBASE_AUTH_CREDENTIALS

通过 Vercel CLI 添加

  1. 使用 CLI 添加带双引号的认证凭据:
    vercel secrets add firebase-auth-credentials '"my-key-here"'
    
  2. 在配置中使用 JSON.parse 解析:
authCredentials: process.env.FIREBASE_AUTH_CREDENTIALS
  ? JSON.parse(process.env.FIREBASE_AUTH_CREDENTIALS)
  : undefined

其他格式处理方案

对于认证凭据中的换行符转义问题,可以采用字符串替换等方法处理。开发者社区中有多种讨论方案可供参考。

使用 Firebase 应用

next-firebase-auth 会自动初始化默认的 Firebase admin 应用和 Firebase JS SDK 应用(如果尚未初始化)。你也可以选择在初始化 next-firebase-auth 之前自行初始化 Firebase。

前端组件中使用示例

import { getApp } from 'firebase/app'
import { getFirestore, collection, onSnapshot } from 'firebase/firestore'
import { useEffect } from 'react'

const Artists = () => {
  const [artists, setArtists] = useState(artists)

  useEffect(() => {
    return onSnapshot(collection(getFirestore(getApp()), 'artists'), (snap) => {
      if (!snap) return
      setArtists(snap.docs.map((doc) => ({ ...doc.data(), key: doc.id })))
    })
  }, [])

  return (
    <div>
      {artists.map((artist) => (
        <div>{artist.name}</div>
      ))}
    </div>
  )
}

后端管理应用中使用示例

import { getAuth } from 'firebase-admin/auth'
import { init } from 'next-firebase-auth'

// 确保为API路由初始化NFA
init({
  // ... 配置
})

const myCode = () => {
  const auth = getAuth()
  // ...
}

用户认证信息获取

在 API 路由中获取用户

可以使用 verifyIdToken 或 getUserFromCookies 方法轻松获取 API 路由中的用户信息。

在独立后端环境中获取用户

如果你的应用需要在独立的后端环境(如API服务)中认证用户:

  1. 安装依赖:next-firebase-auth 和 firebase-admin
  2. 确保环境支持 fetch(必要时添加 polyfill)
  3. 像平常一样初始化 next-firebase-auth
  4. 确保 Firebase admin 和 cookie 设置与 Next.js 应用中的完全一致
  5. 使用 verifyIdToken 或 getUserFromCookies 方法

示例代码:

import { init, getUserFromCookies } from 'next-firebase-auth'
import './fetch-polyfill'

init({
  // ... 配置
})

const myApiHandler = ({ req }) => {
  const user = await getUserFromCookies({
    req,
    includeToken: true,
  })
  // ... 其他逻辑

  return {
    // 返回数据
  }
}

动态重定向

next-firebase-auth 支持根据用户登录状态动态重定向到登录页或应用页,目标URL可以是运行时确定的动态URL。

示例配置:

import { init } from 'next-firebase-auth'
import absoluteUrl from 'next-absolute-url'

const initAuth = () => init({
  authPageURL: ({ ctx }) => {
    const isServerSide = typeof window === 'undefined'
    const origin = isServerSide
      ? absoluteUrl(ctx.req).origin
      : window.location.origin
    const destPath =
      typeof window === 'undefined' ? ctx.resolvedUrl : window.location.href
    const destURL = new URL(destPath, origin)
    return `auth-ssr?destination=${encodeURIComponent(destURL)}`
  },

  appPageURL: ({ ctx }) => {
    // 类似逻辑处理应用页重定向
    // 包含安全验证逻辑
    return destURL
  },

  // ... 其他配置
})

测试与模拟(Jest)

测试使用 next-firebase-auth 的组件时,可以使用 Jest 的手动模拟功能。

基本模拟设置

  1. 在项目根目录创建 __mocks__/next-firebase-auth/index.js
  2. 定义模拟行为:
const { AuthAction } = require('next-firebase-auth')
const NFAMock = jest.createMockFromModule('next-firebase-auth')

module.exports = {
  ...NFAMock,
  init: jest.fn(),
  withUser: jest.fn(() => (wrappedComponent) => wrappedComponent),
  useUser: jest.fn(() => ({
    // 返回默认用户数据
  })),
  AuthAction,
}

用户模拟工具

创建用户模拟生成器:

const mockFirebaseUser = {
  displayName: '测试用户',
  // ... 其他字段
}

const getMockUser = (isLoggedIn = true) => ({
  id: isLoggedIn ? 'test123' : null,
  email: isLoggedIn ? 'test@example.com' : null,
  emailVerified: isLoggedIn,
  getIdToken: jest.fn(async () => (isLoggedIn ? 'test_token' : null)),
  clientInitialized: isLoggedIn,
  firebaseUser: isLoggedIn ? mockFirebaseUser : null,
  signOut: jest.fn(),
  serialize: jest.fn(() => 'serialized_auth_user'),
})

组件测试示例

import { render, screen } from '@testing-library/react'
import { useUser, withUser } from 'next-firebase-auth'
import getMockUser from '../../utils/test-utils/get-mock-auth-user'

jest.mock('next-firebase-auth')

describe('UserDisplayName', () => {
  let UserDisplayName

  beforeEach(() => {
    useUser.mockReturnValue(getMockUser())
    withUser.mockImplementation(() => (wrappedComponent) => wrappedComponent))
    UserDisplayName = require('./').default
  })

  it('显示登录用户的名称', () => {
    render(<UserDisplayName />)
    expect(screen.getByText(getMockUser().firebaseUser.displayName)).toBeInTheDocument()
  })

  it('未登录时显示"anonymous"', () => {
    useUser.mockReturnValue(getMockUser(false))
    render(<Header />)
    expect(screen.getByText('anonymous')).toBeInTheDocument()
  })
})

TypeScript 测试注意事项

在 TypeScript 测试中,需要类型断言来访问 mock 方法:

(useUser as jest.Mock).mockReturnValue(getMockUser())
(withUser as jest.Mock).mockImplementation(() => (wrappedComponent: ComponentType) => wrappedComponent)

通过以上示例和说明,开发者可以全面了解 next-firebase-auth 在不同场景下的使用方法,从而在自己的 Next.js 项目中实现完善的 Firebase 认证功能。

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

万钧瑛Hale

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值