如何保持我的next-auth用户会话并在其他路由中使用提供的ID获取数据?
P粉744691205
P粉744691205 2023-08-25 15:35:57
[React讨论组]

我想在这里实现的是,每当用户登录时,我希望存储返回的数据,因为数据中包含一个我将在其他路由中使用的ID来获取数据。当用户成功登录后,他将被重定向到/home路由,并且从会话中获取的ID将用于获取数据。一切都正常工作,但如果我刷新主页,用户将变为空。

这是我的[...nextauth].js文件的样子。

import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import axios from "axios";

export default NextAuth({
  providers: [
    CredentialsProvider({
      name: "credentials",

      credentials: {
        username: { label: "Username", type: "text", placeholder: "justin" },
        password: {label: "Password",type: "password",placeholder: "******"},
      },

      async authorize(credentials, req) {
        const url = req.body.callbackUrl.split("/auth")[0];
        const { username, password } = credentials;
        const user = await axios({
          url: `${url}/api/user/login`,
          method: "POST",
          data: {
            username: username,
            password: password,
          },
          "content-type": "application/json",
        })
          .then((res) => {
            return res.data;
          })
          .catch((err) => {
            if (err.response.data) {
              throw new Error(err.response.data);
            } else {
              return null;
            }
            return null;
          });
        return user;
      },
    }),
  ],

  callbacks: {
    jwt: ({ token, user }) => {
      if (user) {
        token.user = user;
      }

      return token;
    },
    session: ({ session, token }) => {
      if (token) {
        session.user = token.user;
      }

      return session;
    },
  },

  pages: {
    signIn: "/auth/login",
    newUser: "/auth/register",
  },
});

这是我的/home路由的样子

import Card from "@/components/card/Card";
import React, { useEffect, useState } from "react";
import styles from "./home.module.css";
import { Ubuntu } from "@next/font/google";
import { useSession } from "next-auth/react";
import { useDispatch, useSelector } from "react-redux";

const ubuntu = Ubuntu({ weight: "500", subsets: ["cyrillic"] });
const getData = async (id) => {
  const res = await fetch({
    url: "http://localhost:3000/api/note/getall",
    method: "POST",
    "content-type": "application/json",
    data: {
      id: id,
    },
  });
  if (!res.ok) {
    console.log(id);
    throw new Error("Unable  to fetch");
  } else {
    return res.json();
    console.log(res);
  }
};

function home() {
  const colors = ["#E9F5FC", "#FFF5E1", "#FFE9F3", "#F3F5F7"];
  const random = Math.floor(Math.random() * 5);
  const rc = colors[random];
  const [pop, setPop] = useState("none");
  const { user } = useSelector((state) => state.user);
  const getDataa = async () => {
    console.log(user)
    const data = await getData(user._id);
    console.log(data);
  };
  useEffect(() => {
    if (user) {
      alert(user)
    }
  }, []);
  return (
    <div className={styles.home}>
      <header>
        <h3 className={ubuntu.className}>
          Hello, <br /> {user?.username}!
        </h3>
        <input type="text" placeholder="search" />
      </header>

      <div className={styles.nav}>
        <h1 className={ubuntu.className}>Notes</h1>
      </div>

      <div className={styles.section}>
        <div className={styles.inner}>
          {/*           {data &&
            data.map((e) => (
              <Card
                rawData={e}
                color={colors[Math.floor(Math.random() * colors.length)]}
              />
            ))} */}
        </div>
      </div>

      <div className="new"></div>
    </div>
  );
}

export default home;

P粉744691205
P粉744691205

全部回复(2)
P粉428986744

这段代码似乎会创建一个问题/竞争条件,因为你混合了两种不同的异步Promise处理方式:

const user = await axios({
  url: `${url}/api/user/login`,
  method: "POST",
  data: {
    username: username,
    password: password,
  },
  "content-type": "application/json",
})
  .then((res) => {
    return res.data;
  })
  .catch((err) => {
    if (err.response.data) {
      throw new Error(err.response.data);
    } else {
      return null;
    }
    return null;
  });
return user;

应该改成这样:

try {
  const user = await axios({
    url: `${url}/api/user/login`,
    method: "POST",
    data: {
      username: username,
      password: password,
    },
    "content-type": "application/json",
  });
  return user.data;
} catch (err) {
  if (err.response.data) {
    throw new Error(err.response.data);
  } else {
    return null;
  }
}

或者这样:

axios({
  url: `${url}/api/user/login`,
  method: "POST",
  data: {
    username: username,
    password: password,
  },
  "content-type": "application/json",
}).then((res) => {
  return res.data;
}).catch((err) => {
  if (err.response.data) {
    throw new Error(err.response.data);
  } else {
    return null;
  }
  return null;
});
P粉707235568

将此component添加到您的App.js文件中:

function Auth({ children }) {
  const router = useRouter();
  const { status } = useSession({
    required: true,
    onUnauthenticated() {
      router.push("/sign-in");
    },
  });

  if (status === "loading") {
    return 
Loading ...
; } return children; }

现在在您的App函数中,不再返回<Component {...pageProps} />,而是首先检查component是否具有auth属性,所以您将其包装在<Auth>中,以确保每个需要会话的组件只有在会话加载完成后才会挂载(这就是为什么用户为null,因为会话仍在加载中)

{
  Component.auth ? (
    
  ) : (
    
  );
}

最后,您将.auth = {}添加到您想要定义会话的每个页面中(在您的情况下是Home)

const Home = () => {
//....
}
Home.auth = {};

这还有助于在会话过期时将用户重定向到/sign-in页面

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号