我正在使用 Firebase 身份验证开发 Next JS 应用程序。我已经成功实现了这一点,并且还制作了一个 AuthContext 文件来存储身份验证功能(登录、注册、注销)并管理身份验证状态。这是我的 AuthContext 文件:
const AuthContext = createContext();
export default AuthContext;
export const AuthProvider = ({ children }) => {
const [user, setUser] = useState();
const router = useRouter();
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, (currentUser) => {
setUser(currentUser);
});
return () => unsubscribe();
}, [user]);
const handleRegister = async (e) => {
...
};
const handleLogin = async (e) => {
const formData = new FormData(e.currentTarget);
const email = formData.get("email");
const password = formData.get("password");
await signInWithEmailAndPassword(auth, email, password)
.then((userCredential) => {
router.push("/dashboard");
})
.catch((error) => {
...
});
};
const handleLogout = () => {
signOut(auth);
};
return (
<AuthContext.Provider
value={{
user,
handleRegister,
handleLogin,
handleLogout,
}}
>
{children}
</AuthContext.Provider>
);
};
另外,从 NextJS 文档中我了解到:
Next.js 中的中间件可帮助您控制谁可以访问不同部分 您的网站。这对于保留用户等区域很重要 仪表板受到保护,同时其他页面(例如营销页面)也受到保护 民众。建议在所有路由上应用中间件 指定公共访问的排除项。
所以,我的 middleware.js 文件位于根目录中。并有以下代码:
import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
const currentUser = request.cookies.get('currentUser')?.value
if (currentUser && !request.nextUrl.pathname.startsWith('/dashboard')) {
return Response.redirect(new URL('/dashboard', request.url))
}
if (!currentUser && !request.nextUrl.pathname.startsWith('/login')) {
return Response.redirect(new URL('/login', request.url))
}
}
export const config = {
matcher: ['/((?!api|_next/static|_next/image|.*\\.png$).*)'],
}
但是,我似乎无法如上所述获取 currentUser 。那么,如何使用上下文中的用户状态来访问相同的内容?有什么办法可以做到吗?如果不是,在中间件中获取用户状态的理想方法是什么?
import { getToken } from "next-auth/jwt";
import { NextResponse } from "next/server";
const NEXTAUTH_SECRET = process.env.NEXTAUTH_SECRET;
const SECURE_AUTHENTICATED = '/secret';
export const middleware = async (request) => {
// You can store useful information on the token which you can access
// like firstName, lastName, avatarUrl, etc...
const token = await getToken({ req: request, secret: NEXTAUTH_SECRET });
// use whatever url logic you need to secure your app
if (request.nextUrl.pathname.startsWith(SECURE_AUTHENTICATED) && !token) {
request.nextUrl.pathname = "/auth/login";
return NextResponse.redirect(request.nextUrl);
}
};