Clerk 服务使用笔记,结合 Next.js 和 Hono.js 使用

Clerk 是一个 serverless 登录鉴权服务,支持大量第三方的 OAuth 登录,很方便就能搭建起登录体系,免费额度也较高。结合 Next.js 和 Hono.js 使用可很容易实现前后台全面的鉴权。

Next.js 配置

查看 nextjs 的快速指南:

https://clerk.com/docs/quickstarts/nextjs

npm install @clerk/nextjs

定义环境变量 NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY 和 CLERK_SECRET_KEY

然后使用 ClerkProvider 在 app/layout.tsx 包裹整个应用。

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <ClerkProvider>
      <html lang="en">
        ...
      </html>
    </ClerkProvider>
  )
}

创建登录、导出页

https://clerk.com/docs/references/nextjs/custom-signup-signin-pages

创建 app/sign-in/[[...sign-in]]/page.tsx 导入组件,登出页同理。

import { SignIn } from '@clerk/nextjs'

export default function SignInPage() {
  return <SignIn />
}

环境变量配置:

NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up

用户控件与用户信息

使用用户头像控件:

import { ClerkLoaded, ClerkLoading, UserButton } from "@clerk/nextjs"

<ClerkLoaded>
    <UserButton />
</ClerkLoaded>
<ClerkLoading>
    <Loader2 className="size-8 animate-spin text-slate-400" />
</ClerkLoading>

获取用户信息:

import { useUser } from '@clerk/nextjs';

const { user, isLoaded } = useUser();


{isLoaded ? user?.firstName : ''}

Next.js 中间件拦截登录

通过 middleware.ts 配置拦截,通过白名单形式控制不拦截的页面:

mport { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server'
import { NextResponse } from 'next/server'
const isPublicRoute = createRouteMatcher([
  '/sign-in(.*)',
  '/sign-up(.*)', 
  '/api/(.*)' //不拦截接口, api 使用 hono.js 中间件控制登录状态
])

export default clerkMiddleware(async (auth, request) => {
  if (!isPublicRoute(request)) {
    await auth.protect()
  }
  return NextResponse.next()
})

export const config = {
  matcher: [
    // Skip Next.js internals and all static files, unless found in search params
    '/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)',
    // Always run for API routes
    '/(api|trpc)(.*)',
  ],
}

Hono.js 结合使用

Hono.js 社区有很多中间件:

https://hono.dev/docs/middleware/third-party

Clerk Auth 中间件:

https://github.com/honojs/middleware/tree/main/packages/clerk-auth

为它配置环境变量 CLERK_PUBLISHABLE_KEY ,也就是把之前的 NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY 复制一份。

可结合一个全局中间件,控制所有接口的登录情况,并统一返回:

app.use('*', clerkMiddleware(), async (c, next) => {
    const auth = getAuth(c)
    if (!auth?.userId) {
        throw new HTTPException(401, {
            res: c.json({ error: "未登录" })
        })
    }
    await next()
})

在路由代码中获取用户信息:

import { getAuth } from '@hono/clerk-auth';

const auth = getAuth(c);

console.log(auth.userId)

这样就可以结合 Hono.js 和 Next.js 的登录,达到一体化控制,页面未登录重定向到登录页,接口未登录返回 json 格式。Next Auth 也可以使用类似的配置方式。

本文收录于专栏
使用 Next.js 搭建 SSR 全栈 demo ,以及构建 SSG 纯静态博客,记录学习和使用笔记
收集一些好用的前端开源库,主要是 npm 包