有人在 next.js 中用过 nextAuth 吗?想问个问题

2023-01-19 14:25:57 +08:00
 philsky28

我想实现一下 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",
1605 次点击
所在节点    问与答
2 条回复
violetlai
2023-01-19 15:31:53 +08:00
感觉你的登录流程有点奇怪,主要需求是 token 持久化?

最近我也在做 ssr 只不过使用了 Nuxt3 ,登录流程是客户端发请求=》服务端处理返回结果 token=》保存 session=》 redis?=》 set-cookie=》拿 cookie
可以参考下
philsky28
2023-01-19 17:11:21 +08:00
@violetlai 是为了 token 持久化,以前直接放在了 localStorage 里,但是用 SSR 时,getserversideprops 方法中实际环境是服务端,没法拿到浏览器环境的 token ,所以现在改用 session 存储

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/909872

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX