我想使用 Next-Auth 实现会话管理系统

Posted

技术标签:

【中文标题】我想使用 Next-Auth 实现会话管理系统【英文标题】:I want to implement a sessions management system using Next-Auth 【发布时间】:2022-01-07 09:01:41 【问题描述】:

我想实现一个管理会话系统,以便用户在更改密码时可以注销所有会话。

1-当用户登录时,我会将他的会话存储到用户会话数组中:

2- 我会检查当前会话是否存储在数据库中,如果没有,我会将他注销。

3- 我想添加一个“注销所有会话”按钮,用于注销除当前会话之外的所有会话。

但我不知道如何开始,因为当用户登录时我只有:


  user:  uid: '61a53559b7a09ec93f45f6ad' ,
  expires: '2021-12-30T16:34:58.437Z',
  accessToken: undefined


  user:  uid: '61a53559b7a09ec93f45f6ad' ,
  iat: 1638290097,
  exp: 1640882097,
  jti: '2fc85541-eb9b-475e-8261-50c874f85b51'

我的 [next-auth].js :

import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import mongoose from "mongoose";
import  compare  from "bcrypt";
import  User  from "../auth/signup"

export default NextAuth(
    //configure json web token
    session: 
        strategy: "jwt",
        maxAge: 30 * 24 * 60 * 60,
        updateAge: 24 * 60 * 60,
    ,
    providers: [
        
        CredentialsProvider(
            async authorize(credentials)
                //connect to database
                const client = await mongoose.connect(process.env.DB_URI);
                //search for user using email or username
                const result = await User.findOne($or: [email: credentials.username, username: credentials.username]);
                //if not found
                if(!result)
                    client.connection.close();
                    throw new Error("Incorrect username or password.");
                
                const checkPassword = await compare(credentials.password, result.password);
                //of password doesn't match
                if(!checkPassword)
                    client.connection.close();
                    throw new Error("Incorrect username or password.")
                
                
                client.connection.close();

                if(!result.emailVerified.verified)
                    client.connection.close();
                    throw new Error("Please verify your email adress.") 
                

                return 
                   uid: result._id
                ;
            
        ),
    ], 
    callbacks: 
        async jwt( token, user, account )
            if (account) 
                token.accessToken = account.access_token
            

            user && (token.user = user)
            return token
        ,
        async session( session, token )
            session.user = token.user;
            session.accessToken = token.accessToken;
            
            return session;
        
    

);

【问题讨论】:

【参考方案1】:

我为每个用户创建了一个会话数组,当用户登录时,我生成一个随机哈希键并将其保存到这个数组中(您可以添加自定义属性,例如 IP、时间.. 等),然后保存这个哈希到cookies,然后我在getServerSideProps中添加了一个请求

export async function getServerSideProps(context)

    const data: isAuthenticated = await axios.get(`$process.env.WEB_URI/api/auth/verify/session`, 
      headers: 
        cookie: context.req.headers.cookie
      
    );

/api/auth/verify/session.js

export default async function session(req, res)

    if(req.method === "GET")
        const session = await getSession(req: req);
        if(!session)
         return res.send(false);
        

        mongoose.connect(process.env.DB_URI, useUnifiedTopology: true , async function(error) 
            if(!error)    
                const user = await User.findOne(uid: session.user.uid, _id: 0, sessions: 1);
                
                if(!user)
                    return res.send(false);
                

                const userSession = user.sessions;
                if(userSession.length > 0)
                    const tokens = userSession.map((session => session.token));
                    
                    if(tokens.includes(session.user.token))
                        res.send(true);
                    else
                        res.send(false);
                    
                else
                    res.send(false);
                
            
        );
  

终于

 if(props.isAuthenticated === false)
        signOut();
    

【讨论】:

以上是关于我想使用 Next-Auth 实现会话管理系统的主要内容,如果未能解决你的问题,请参考以下文章

Next-auth - 如何更新会话客户端?

为啥切换语言环境时我的会话没有加载?

如何在 next-auth 中向客户端 API 添加数据?

如何从请求中解析 JWT 令牌 [Next-Auth]

登录后在哪里以及如何更改会话用户对象?

下一个认证 |当用户对象有太多项目时,会话请求没有数据