我想实现一下 SSR 功能,具体流程是这样,先是在登录页登录,然后调用 nextAuth 的 signin 方法,登录成功 token 会放到 session 里,之后跳转首页调用GetServerSideProps
,里面发起 fetch 拿数据。 但是在第一次进入首页时发现GetServerSideProps
中利用 nextAuth 的 apigetSession
获取的 session 是 null ,组件内部能获得,并且 terminal 报错message: 'decryption operation failed'
。但是一刷新后 session 又能正常获得了,控制台也没有报错,不知道有没有人遇到过和我一样的情况?代码如下:
// [...nextauth].ts export default NextAuth({ session: { strategy: "jwt", }, providers: [ CredentialsProvider({ name: "xxx", id: "credentials", credentials: { phone: { label: "手机号", type: "text", }, code: { label: "验证码", type: "text" }, }, async authorize(credentials) { const params = { phone: credentials?.phone ?? "", code: credentials?.code ?? "", }; const env = process.env.H5_OPERATION_ENV || process.env.NODE_ENV; let host; switch (env) { case "DEV": host = "xxx"; break; case "qa": host = "xxx"; break; case "prod": host = "xxx; break; default: break; } const res = await request.get( xxx, { params } ); const user = await res.payLoad; if (res.status === "SUCCESS" && user) { return user; } else { throw new Error(res.error); } }, }), ], pages: { signIn: "/Login/", }, callbacks: { async jwt({ token, user }) { if (user) { token.accessToken = (user as any)?.accessToken; token.name = (user as any)?.loginUserName as string; } return token; }, async session({ session, token }) { (session as Session & { accessToken: string | undefined }).accessToken = token.accessToken as string; if (session.user) { session.user.name = token.name as string; } return session; }, signIn({ user }) { request.interceptors.request.use((url, opts) => { let headers: { Authorization?: string } = {}; if ((user as any)?.accessToken) { headers.Authorization = `API-Bearer ${(user as any).accessToken}`; } return { url, options: { ...opts, ...headers }, }; }); return true; }, }, secret: process.env.NEXTAUTH_SECRET, debug: true, });
// .env.development H5_OPERATION_ENV = DEV NEXTAUTH_URL_INTERNAL = http://localhost:3000/ NEXTAUTH_URL = http://localhost:3000/ NEXTAUTH_SECRET = xxx
// login.tsx const login = async (values: any) => { const res = await signIn('credentials', { ...values, redirect: false }) if (res?.ok) { const session = await getSession() getUserAuth({ currentUser: session?.user?.name ?? '' }).then(res => { if (res?.status === 'SUCCESS') { dispatch({ type: 'setState', payload: { powerList: res?.payLoad?.powerList?.map((power: any) => power?.powerCode) } }) } }) router.push('/home') }
//home.tsx export const getServerSideProps: GetServerSideProps<IndexProps> = async cOntext=> { const session = await getSession(context); console.log(session, 'first getServerSideProps'); // 第一次进入返回了 null let data: never[] = [] if ((session as any)?.accessToken) { console.log(session, 'getServerSidePropsGetSession'); const res = await fetch(`http://xxx`, { headers: { Authorization: `API-Bearer ${(session as any).accessToken}` } }) await res?.json().then(respOnse=> { console.log(data, 'json()'); if (response.status === 'SUCCESS') { data = response.payLoad.list } }) } return { props: { list: JSON.stringify(data) ?? [] } } } export default function Home(props: IndexProps) { const { data: session } = useSession() // 这里是 ok 的 }
// package.json "next": "12.2.3", "next-auth": "^4.10.3",
![]() | 1 violetlai 2023-01-19 15:31:53 +08:00 感觉你的登录流程有点奇怪,主要需求是 token 持久化? 最近我也在做 ssr 只不过使用了 Nuxt3 ,登录流程是客户端发请求=》服务端处理返回结果 token=》保存 session=》 redis?=》 set-cookie=》拿 cookie 可以参考下 |