如何保持我的next-auth用户会话并在其他路由中使用提供的ID获取数据?
P粉744691205
P粉744691205 2023-08-25 15:35:57
0
2
501
<p>我想在这里实现的是,每当用户登录时,我希望存储返回的数据,因为数据中包含一个我将在其他路由中使用的ID来获取数据。当用户成功登录后,他将被重定向到/home路由,并且从会话中获取的ID将用于获取数据。一切都正常工作,但如果我刷新主页,用户将变为空。</p> <p>这是我的[...nextauth].js文件的样子。</p>
从“next-auth”导入 NextAuth;
从“next-auth/providers/credentials”导入 CredentialsProvider;
从“axios”导入 axios;

导出默认 NextAuth({
  提供者:[
    凭证提供者({
      名称:“凭证”,

      证书: {
        用户名:{ 标签:“用户名”,类型:“文本”,占位符:“贾斯汀” },
        密码:{标签:“密码”,类型:“密码”,占位符:“******”},
      },

      异步授权(凭据,请求){
        const url = req.body.callbackUrl.split(“/auth”)[0];
        const { 用户名,密码 } = 凭据;
        const 用户 = 等待 axios({
          url: `${url}/api/user/login`,
          方法:“POST”,
          数据: {
            用户名: 用户名,
            密码: 密码,
          },
          “内容类型”:“application/json”,
        })
          .then((res) => {
            返回res.data;
          })
          .catch((错误) => {
            if (err.response.data) {
              抛出新错误(err.response.data);
            } 别的 {
              返回空值;
            }
            返回空值;
          });
        返回用户;
      },
    }),
  ],

  回调:{
    jwt: ({ 令牌, 用户 }) => {
      如果(用户){
        token.user = 用户;
      }

      返回令牌;
    },
    会话:({会话,令牌})=> {
      如果(令牌){
        会话.用户 = 令牌.用户;
      }

      返回会话;
    },
  },

  页数:{
    登录:“/auth/login”,
    新用户:“/auth/register”,
  },
});</pre>
<p>这是我的/home路由的感觉</p>
从“@/components/card/Card”导入卡;
从“react”导入 React, { useEffect, useState };
从“./home.module.css”导入样式;
从“@next/font/google”导入 { Ubuntu };
从“next-auth/react”导入{useSession};
从“react-redux”导入{useDispatch,useSelector};

const ubuntu = Ubuntu({ 权重: "500", 子集: ["西里尔文"] });
const getData = async (id) =>; {
  const res = 等待获取({
    url: "http://localhost:3000/api/note/getall",
    方法:“POST”,
    “内容类型”:“application/json”,
    数据: {
      身份证号: 身份证号,
    },
  });
  如果(!res.ok){
    控制台.log(id);
    throw new Error(“无法获取”);
  } 别的 {
    返回 res.json();
    控制台.log(res);
  }
};

函数主页(){
  const 颜色 = [“#E9F5FC”、“#FFF5E1”、“#FFE9F3”、“#F3F5F7”];
  const random = Math.floor(Math.random() * 5);
  const rc = 颜色[随机];
  const [pop, setPop] = useState(“无”);
  const { user } = useSelector((state) => state.user);
  const getDataa = async () =>; {
    控制台.log(用户)
    const data =等待 getData(user._id);
    控制台.log(数据);
  };
  useEffect(() => {
    如果(用户){
      警报(用户)
    }
  }, []);
  返回 (
    
; <标题> <h3 className={ubuntu.className}> 你好,<br />> {用户?.用户名}! </h3> <输入类型=“文本”;占位符=“搜索” >> </标题> <div className={styles.nav}>

注释

<div className={styles.section}> <div className={styles.inner}> {/* {数据&& 数据.map((e) => ( <卡 原始数据={e} 颜色={颜色[Math.floor(Math.random() * color.length)]} >> ))} */}
); } 导出默认主页;</pre></p>
2
0
0
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页面

热门专题
更多>
热门文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板