8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

确保会话管理规则在浏览器刷新后仍然有效

maidan 2月前

15 0

'使用客户端';导入 React,{ useContext、createContext、useState、useEffect } 来自'react';导入 { setPersistence、signInWithEmailAndPassword、signOut、onAuthStateChanged、User、

'use client';
import React, { useContext, createContext, useState, useEffect } from 'react';
import {
  setPersistence,
  signInWithEmailAndPassword,
  signOut,
  onAuthStateChanged,
  User,
  browserSessionPersistence,

} from 'firebase/auth';
import Loading from '../components/pages/Loading';
import { doc, collection, getDocs, setDoc, deleteDoc, orderBy, limit, query, onSnapshot } from 'firebase/firestore';
import { auth, firestore } from '../firebase-config';
import { CollectionReference, DocumentData } from 'firebase/firestore';

export interface AuthContextType {
  user: User | null;
  emailSignIn: (email: string, password: string) => Promise<void>;
  logout: () => Promise<void>;
}

const AuthContext = createContext<AuthContextType | null>(null);

export const AuthContextProvider = ({ children }: Readonly<{ children: React.ReactNode }>) => {
  const [user, setUser] = useState<User | null>(null);
  const [loading, setLoading] = useState(true);

  const emailSignIn = async (email: string, password: string) => {
    try {
      await setPersistence(auth, browserSessionPersistence);
      const userCredential = await signInWithEmailAndPassword(auth, email, password);
      setUser(userCredential.user);
 
      if (!userCredential.user.email) {
          throw new Error('User email is not available.');
        }

      const sessionsRef = collection(firestore, 'users', userCredential.user.email, 'sessions'); 
      const sessionsSnapshot = await getDocs(sessionsRef);
      
      if (sessionsSnapshot.size >=2) {
        await removeOldestSession(sessionsRef);
      }
    
      const sessionId = generateDeviceId();
      await setDoc(doc(sessionsRef, sessionId), {
        deviceId: sessionId,
        timestamp: new Date(),
      });
      
      monitorSession(sessionsRef, sessionId); // Start monitoring the session

    } catch (error) {
      console.error('Error signing in with email: ', error);
      throw error;
    }
  };

const removeOldestSession = async (sessionsRef: CollectionReference<DocumentData>) => {
  const sessionsQuery = query(sessionsRef, orderBy('timestamp', 'asc'), limit(1)); 
  const querySnapshot = await getDocs(sessionsQuery);

  if (!querySnapshot.empty) {
    const oldestSession = querySnapshot.docs[0];
    await deleteDoc(oldestSession.ref);
  }
};

  const generateDeviceId = () => {
    return Math.random().toString(36).substring(2);
  };

    const monitorSession = (sessionsRef: CollectionReference<DocumentData>, sessionId: string) => {
    const sessionDocRef = doc(sessionsRef, sessionId);
    const unsubscribe = onSnapshot(sessionDocRef, (docSnapshot) => {
      if (!docSnapshot.exists()) {
        // If the session document is deleted, log the user out
        logout();
      }
    });

    return () => unsubscribe();
  };


  const logout = async () => {
    try {
   if (user) {
    
    if (!user.email) {
      throw new Error('User email is not available.');
    }

      const sessionsRef = collection(firestore, 'users', user.email, 'sessions');
      const sessionQuery = query(sessionsRef, orderBy('timestamp', 'desc'), limit(1));
      const querySnapshot = await getDocs(sessionQuery);

      if (!querySnapshot.empty) {
        const sessionDoc = querySnapshot.docs[0];
        await deleteDoc(sessionDoc.ref);
      }
    }

      await signOut(auth);
      setUser(null);
    } catch (error) {
      console.error('Error signing out: ', error);
      throw error;
    }
  };

useEffect(() => {
  const unsubscribe = onAuthStateChanged(auth, async (currentUser) => {
    setLoading(true); 
    if (currentUser) {
      setUser(currentUser);
    } else {
      setUser(null); 
    }
    setLoading(false);
  });

  return () => unsubscribe(); 
}, []); 
  

  if (loading) {
    return <Loading />;
  }

  return (
    <AuthContext.Provider value={{ user, emailSignIn, logout}}>{children}</AuthContext.Provider>
  );
};

export const UserAuth = () => {
  const context = useContext(AuthContext);
  if (!context) {
    throw new Error('useAuth must be used within an AuthContextProvider');
  }
  return context;
};

当第三个浏览器尝试以同一用户身份登录时,我的代码可以正确注销最早的会话。但是,我遇到了一个问题,如果刷新浏览器,会话管理规则将不再适用于该浏览器。如何确保即使刷新浏览器,会话限制规则仍会继续执行?

我尝试将数据保存在本地存储中,但没有成功

帖子版权声明 1、本帖标题:确保会话管理规则在浏览器刷新后仍然有效
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由maidan在本站《javascript》版块原创发布, 转载请注明出处!
最新回复 (0)
返回
作者最近主题: