身份驗證
身份驗證 (Authentication) 用於確認使用者身份,而授權 (Authorization) 則控制使用者能訪問的內容。Next.js 支援多種身份驗證模式,每種模式針對不同的使用情境設計。本頁將逐一介紹這些模式,幫助您根據需求做出選擇。
身份驗證模式
選擇身份驗證模式的第一步是了解您所需的資料獲取策略。接著我們可以確定哪些身份驗證供應商支援該策略。主要有兩種模式:
- 使用靜態生成 (Static Generation) 在伺服器端渲染載入狀態,然後在客戶端獲取使用者資料。
- 透過伺服器端渲染 (Server-side Rendering) 獲取使用者資料,避免出現未驗證內容的閃爍。
驗證靜態生成頁面
當頁面沒有阻塞性資料需求時,Next.js 會自動判定該頁面為靜態頁面。這表示頁面中不存在 getServerSideProps
和 getInitialProps
。此時您的頁面可以先從伺服器渲染載入狀態,然後在客戶端獲取使用者資料。
這種模式的優勢在於頁面可以透過全球 CDN 提供服務,並使用 next/link
進行預載。實際上,這能縮短 TTI (互動時間)。
以下是一個個人資料頁面的範例。它會先渲染載入骨架圖,當使用者資料請求完成後,顯示使用者名稱:
import useUser from '../lib/useUser'
import Layout from '../components/Layout'
const Profile = () => {
// 在客戶端獲取使用者資料
const { user } = useUser({ redirectTo: '/login' })
// 伺服器端渲染載入狀態
if (!user || user.isLoggedIn === false) {
return <Layout>載入中...</Layout>
}
// 當使用者請求完成後,顯示使用者資料
return (
<Layout>
<h1>您的個人資料</h1>
<pre>{JSON.stringify(user, null, 2)}</pre>
</Layout>
)
}
export default Profile
您可以查看實際運作的範例。參考 with-iron-session
範例了解其運作原理。
驗證伺服器端渲染頁面
如果您從頁面中匯出名為 getServerSideProps
的 async
函數,Next.js 會在每次請求時使用該函數返回的資料預先渲染頁面。
export async function getServerSideProps(context) {
return {
props: {}, // 將作為 props 傳遞給頁面元件
}
}
讓我們將個人資料範例改為使用伺服器端渲染。如果有會話存在,將 user
作為 prop 傳遞給頁面中的 Profile
元件。請注意此範例中沒有載入骨架圖。
import withSession from '../lib/session'
import Layout from '../components/Layout'
export const getServerSideProps = withSession(async function ({ req, res }) {
const { user } = req.session
if (!user) {
return {
redirect: {
destination: '/login',
permanent: false,
},
}
}
return {
props: { user },
}
})
const Profile = ({ user }) => {
// 顯示使用者資料。無需載入狀態
return (
<Layout>
<h1>您的個人資料</h1>
<pre>{JSON.stringify(user, null, 2)}</pre>
</Layout>
)
}
export default Profile
這種模式的優勢在於能避免在重新導向前出現未驗證內容的閃爍。需要注意的是,在 getServerSideProps
中獲取使用者資料會阻塞渲染,直到身份驗證供應商的請求完成。為避免造成瓶頸並增加 TTFB (首字節時間),您應確保身份驗證查詢速度夠快。否則,請考慮使用靜態生成。
身份驗證供應商
現在我們已討論了身份驗證模式,接下來看看具體的供應商及其在 Next.js 中的使用方式。
使用自有資料庫
如果您已有包含使用者資料的資料庫,可能會想使用與供應商無關的開源解決方案:
- 如需低階、加密且無狀態的會話工具,請使用
iron-session
。 - 如需功能完整的身份驗證系統,包含內建供應商 (Google、Facebook、GitHub...)、JWT、JWE、電子郵件/密碼、魔法連結等,請使用
next-auth
。
這兩種函式庫都支援上述身份驗證模式。如果您對 Passport 感興趣,我們也提供了使用安全加密 cookie 的範例:
其他供應商
如需查看其他身份驗證供應商的範例,請參閱 examples 資料夾。