您好!欢迎来到源码码网

大型后台管理系统,用户登录状态该如何保存?

  • 源码教程
  • 来源:源码码网
  • 编辑:源码码网
  • 时间:2025-11-06 12:16
  • 阅读:437

大型后台管理系统的用户登录状态保存需要综合考虑安全性用户体验系统架构。以下是企业级的完整方案:

1. 多层级存储策略

class AuthManager {
    constructor() {
        this.storage = {
            // 内存存储(最高安全)
            memory: new Map(),
            
            // 会话级存储(较高安全)
            session: sessionStorage,
            
            // 持久化存储(用户偏好)
            local: localStorage,
            
            // 自动传输存储(兼容性)
            cookie: this.cookieManager
        }
    }
    
    // 分级存储策略
    setLoginState(userData) {
        // 1. 敏感数据 - 内存存储(刷新即失)
        this.storage.memory.set('access_token', userData.accessToken)
        this.storage.memory.set('session_key', userData.sessionKey)
        
        // 2. 刷新令牌 - HttpOnly Cookie(防XSS)
        this.setHttpOnlyCookie('refresh_token', userData.refreshToken, {
            maxAge: 7 * 24 * 60 * 60, // 7天
            httpOnly: true,
            secure: true,
            sameSite: 'strict'
        })
        
        // 3. 用户基本信息 - localStorage(持久化)
        this.storage.local.setItem('user_info', JSON.stringify({
            id: userData.id,
            name: userData.name,
            avatar: userData.avatar,
            roles: userData.roles,
            permissions: userData.permissions
        }))
        
        // 4. 登录状态标识 - sessionStorage(标签页级)
        this.storage.session.setItem('is_logged_in', 'true')
        this.storage.session.setItem('login_timestamp', Date.now())
        
        // 5. 辅助信息 - 普通Cookie
        this.setCookie('user_theme', userData.theme, { maxAge: 30 * 24 * 60 * 60 })
    }
}

2. Token 双令牌机制

class TokenService {
    constructor() {
        this.accessToken = null
        this.refreshToken = null
        this.tokenRefreshTimeout = null
    }
    
    // 设置双令牌
    setTokens(accessToken, refreshToken) {
        // Access Token - 短期(内存 + 备用localStorage)
        this.accessToken = accessToken
        localStorage.setItem('access_token_backup', accessToken)
        localStorage.setItem('access_token_expire', Date.now() + 2 * 60 * 60 * 1000) // 2小时
        
        // Refresh Token - 长期(HttpOnly Cookie)
        this.setHttpOnlyCookie('refresh_token', refreshToken, {
            maxAge: 7 * 24 * 60 * 60,
            httpOnly: true,
            secure: true
        })
        
        // 启动token自动刷新
        this.startTokenRefresh()
    }
    
    // 自动刷新token
    startTokenRefresh() {
        // 在token过期前5分钟自动刷新
        const refreshTime = 115 * 60 * 1000 // 115分钟
        
        this.tokenRefreshTimeout = setTimeout(async () => {
            try {
                await this.refreshAccessToken()
            } catch (error) {
                console.error('Token自动刷新失败:', error)
                this.handleTokenRefreshFailed()
            }
        }, refreshTime)
    }
    
    // 刷新access token
    async refreshAccessToken() {
        const refreshToken = this.getRefreshToken()
        
        const response = await fetch('/api/auth/refresh', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({ refreshToken })
        })
        
        if (response.ok) {
            const data = await response.json()
            this.setTokens(data.accessToken, data.refreshToken)
            return data.accessToken
        } else {
            throw new Error('刷新token失败')
        }
    }
}

3. 应用启动状态恢复

class AppInitializer {
    constructor() {
        this.authManager = new AuthManager()
        this.tokenService = new TokenService()
    }
    
    // 应用启动时恢复登录状态
    async initializeApp() {
        console.log('🚀 应用初始化...')
        
        // 1. 检查内存中的token(最高优先级)
        if (this.tokenService.accessToken) {
            console.log('✅ 内存中存在有效token')
            return await this.validateCurrentToken()
        }
        
        // 2. 检查备份的access token
        const backupToken = localStorage.getItem('access_token_backup')
        const tokenExpire = localStorage.getItem('access_token_expire')
        
        if (backupToken && tokenExpire && Date.now() < parseInt(tokenExpire)) {
            console.log('✅ 使用备份token恢复')
            this.tokenService.accessToken = backupToken
            return await this.validateCurrentToken()
        }
        
        // 3. 尝试使用refresh token刷新
        if (this.getRefreshToken()) {
            console.log('🔄 尝试刷新token...')
            try {
                await this.tokenService.refreshAccessToken()
                return await this.validateCurrentToken()
            } catch (error) {
                console.log('❌ token刷新失败')
                this.clearAuthState()
            }
        }
        
        // 4. 最终检查session状态
        if (sessionStorage.getItem('is_logged_in') === 'true') {
            console.log('🔍 会话状态存在,但token无效')
            // 可能需要重新认证
        }
        
        // 5. 未登录状态
        console.log('🔒 用户未登录')
        this.redirectToLogin()
    }
    
    // 验证当前token有效性
    async validateCurrentToken() {
        try {
            const response = await fetch('/api/auth/validate', {
                headers: {
                    'Authorization': `Bearer ${this.tokenService.accessToken}`
                }
            })
            
            if (response.ok) {
                const userData = await response.json()
                this.authManager.setUserData(userData)
                console.log('✅ 登录状态验证成功')
                return true
            } else {
                throw new Error('Token验证失败')
            }
        } catch (error) {
            console.error('❌ Token验证失败:', error)
            this.clearAuthState()
            return false
        }
    }
}

4. 请求拦截与自动处理

// axios请求拦截配置
import axios from 'axios'

class RequestInterceptor {
    constructor() {
        this.setupInterceptors()
    }
    
    setupInterceptors() {
        // 请求拦截器
        axios.interceptors.request.use(
            (config) => {
                const token = this.getAccessToken()
                if (token) {
                    config.headers.Authorization = `Bearer ${token}`
                }
                return config
            },
            (error) => Promise.reject(error)
        )
        
        // 响应拦截器 - 处理认证失败
        axios.interceptors.response.use(
            (response) => response,
            async (error) => {
                const originalRequest = error.config
                
                // 处理401错误(未认证)
                if (error.response?.status === 401 && !originalRequest._retry) {
                    originalRequest._retry = true
                    
                    try {
                        // 尝试刷新token
                        const newToken = await this.tokenService.refreshAccessToken()
                        originalRequest.headers.Authorization = `Bearer ${newToken}`
                        return axios(originalRequest)
                    } catch (refreshError) {
                        // 刷新失败,清除登录状态
                        this.clearAuthState()
                        this.redirectToLogin()
                        return Promise.reject(refreshError)
                    }
                }
                
                // 处理403错误(权限不足)
                if (error.response?.status === 403) {
                    this.showPermissionDenied()
                    return Promise.reject(error)
                }
                
                return Promise.reject(error)
            }
        )
    }
}

5. 安全增强措施

class SecurityEnhancer {
    constructor() {
        this.setupSecurityMeasures()
    }
    
    setupSecurityMeasures() {
        // 1. 防止XSS攻击
        this.sanitizeStorage()
        
        // 2. 设置安全头
        this.setSecurityHeaders()
        
        // 3. 监听异常行为
        this.setupBehaviorMonitoring()
    }
    
    // 存储数据清理
    sanitizeStorage() {
        // 定期清理过期的存储数据
        setInterval(() => {
            this.cleanExpiredStorage()
        }, 60 * 60 * 1000) // 每小时清理一次
    }
    
    // 行为监控
    setupBehaviorMonitoring() {
        // 监听多标签页登录冲突
        window.addEventListener('storage', (event) => {
            if (event.key === 'login_conflict' && event.newValue) {
                this.handleLoginConflict()
            }
        })
        
        // 监听用户活跃度
        this.setupActivityMonitoring()
    }
    
    // 用户活跃度监控
    setupActivityMonitoring() {
        let lastActivityTime = Date.now()
        
        const updateActivityTime = () => {
            lastActivityTime = Date.now()
        }
        
        // 监听用户操作
        ['mousedown', 'keypress', 'scroll', 'touchstart'].forEach(event => {
            document.addEventListener(event, updateActivityTime, true)
        })
        
        // 检查用户是否活跃
        setInterval(() => {
            const inactiveTime = Date.now() - lastActivityTime
            if (inactiveTime > 30 * 60 * 1000) { // 30分钟无操作
                this.handleUserInactive()
            }
        }, 60 * 1000) // 每分钟检查一次
    }
}

6. 完整的登录状态管理

// 主入口文件 - main.js
import { createApp } from 'vue'
import App from './App.vue'
import { AuthManager, TokenService, AppInitializer } from './services/auth'

const app = createApp(App)

// 初始化认证服务
const authManager = new AuthManager()
const tokenService = new TokenService()
const appInitializer = new AppInitializer(authManager, tokenService)

// 全局提供认证服务
app.provide('authManager', authManager)
app.provide('tokenService', tokenService)

// 应用启动
appInitializer.initializeApp().then((isAuthenticated) => {
    if (isAuthenticated) {
        console.log('✅ 应用启动完成 - 用户已登录')
        app.mount('#app')
    } else {
        console.log('🔒 应用启动完成 - 用户未登录')
        // 可以挂载应用但显示登录界面
        app.mount('#app')
    }
}).catch((error) => {
    console.error('❌ 应用启动失败:', error)
    // 错误处理
})

7. 不同场景的配置方案

// 安全等级配置
export const SECURITY_LEVELS = {
    // 金融级安全
    FINANCE: {
        accessTokenExpire: 15 * 60, // 15分钟
        refreshTokenExpire: 24 * 60 * 60, // 24小时
        autoLogout: 30 * 60, // 30分钟无操作自动登出
        multiFactorAuth: true,
        sessionPerDevice: true
    },
    
    // 企业级安全
    ENTERPRISE: {
        accessTokenExpire: 2 * 60 * 60, // 2小时
        refreshTokenExpire: 7 * 24 * 60 * 60, // 7天
        autoLogout: 60 * 60, // 1小时无操作
        multiFactorAuth: false,
        sessionPerDevice: false
    },
    
    // 内部系统
    INTERNAL: {
        accessTokenExpire: 8 * 60 * 60, // 8小时
        refreshTokenExpire: 30 * 24 * 60 * 60, // 30天
        autoLogout: 4 * 60 * 60, // 4小时无操作
        multiFactorAuth: false,
        rememberMe: true
    }
}

总结

大型后台管理系统的登录状态管理应该是:

  1. 分层存储:敏感数据存内存,持久数据存localStorage,自动传输用Cookie

  2. 双令牌机制:短期access token + 长期refresh token

  3. 自动恢复:应用启动时智能恢复登录状态

  4. 安全增强:XSS防护、行为监控、自动登出

  5. 错误处理:完善的token刷新和错误处理机制

  6. 灵活配置:根据不同安全需求调整策略

这样的设计既保证了安全性,又提供了良好的用户体验。


特别声明:
1、如无特殊说明,内容均为本站原创发布,转载请注明出处;
2、部分转载文章已注明出处,转载目的为学习和交流,如有侵犯,请联系客服删除;
3、编辑非《源码码网》的文章均由用户编辑发布,不代表本站立场,如涉及侵犯,请联系删除;
全部评论(0)
推荐阅读
  • 常用测试压力工具使用介绍
  • 常用测试压力工具使用介绍
  • ab 是 ApacheBench 工具的缩写,它是一个HTTP压力测试工具。让我详细说明如何测试:1. 安装ApacheBenchWindows系统:方法一:安装XAMPP或WAMP(自带ab)下载地址:https://www.apachefriends.org/zh_cn/index.html安装后,ab工具在:C:xamppapacheinab.exe方法二:使
  • 开发工具
  • 来源:源码码网
  • 编辑:源码码网
  • 时间:2026-01-13 20:27
  • 阅读:82
  • 工程项目一体化自动管理软件解决方案
  • 工程项目一体化自动管理软件解决方案
  • 1.项目概述1.1项目背景在工程建设行业数字化转型浪潮下,传统项目管理面临信息孤岛、协同困难、进度不可控、成本超支等痛点。本方案旨在构建一个覆盖工程项目全生命周期、全参与方、全业务流程的一体化智能管理平台。1.2解决方案愿景打造数据驱动、智能协同、风险预警、自动执行的工程大脑,实现:管理流程自动化率≥80%项目协同效率提升40%成本偏差率降低至±3%以内安全事故发生率降低60%1.3目标用户矩阵┌───────────────┬
  • 行业资讯
  • 来源:源码码网
  • 编辑:源码码网
  • 时间:2026-01-09 11:26
  • 阅读:207
  • 车辆管理系统需求文档与技术架构PC端+小程序
  • 车辆管理系统需求文档与技术架构PC端+小程序
  • 第一部分:需求文档1.项目概述1.1项目背景为企事业单位、车队运营商、租赁公司等提供一套完整的车辆全生命周期管理解决方案,实现车辆管理数字化、智能化。1.2项目目标建立车辆从购置到报废的全流程管理体系实现用车申请、调度、监控、结算的闭环管理通过数据分析优化车辆使用效率降低车辆运维成本20%以上1.3用户角色矩阵┌──────────────┬─────────────────────────────┬──────────────
  • 行业资讯
  • 来源:源码码网
  • 编辑:源码码网
  • 时间:2026-01-09 11:11
  • 阅读:194
  • 智慧农业/渔业物联网系统需求文档
  • 智慧农业/渔业物联网系统需求文档
  • 智慧农业/渔业物联网系统需求文档文档版本: V1.0项目目标: 构建一个集环境智能监测、设备自动化控制、生长模型分析、溯源管理与远程指挥于一体的综合物联网管理平台,实现降本增效、提质增产、风险预警与品牌增值。1.系统总体概述1.1核心价值: 数据驱动决策,解放人力,实现农业/渔业生产的精准化、自动化与智能化。1.2用户角色:生产员/养殖员: 现场巡视、接收告警、执行设备手动控制、查看实时环境
  • 行业资讯
  • 来源:源码码网
  • 编辑:源码码网
  • 时间:2026-01-09 11:04
  • 阅读:93
  • 程序员AI编程工具推荐
  • 程序员AI编程工具推荐
  • AI编程工具是当前开发者的“副驾驶”,能够极大提升开发效率。以下我将从通用型、代码专用型、垂直领域型以及开源/自部署型几个维度为您分类推荐,并附上它们的核心特点和适用场景,帮助您选择。一、通用型AI对话助手(编程是核心能力之一)这类工具本质是“更懂代码的ChatGPT”,适合处理广泛的编程问题、解释代码、生成文档等。ChatGPT(GPT-4/4o)简介:行业标杆,尤其在GPT-4版本下,代码理解和生成能力极强。优点:上下文能力强,
  • 源码教程
  • 来源:源码码网
  • 编辑:源码码网
  • 时间:2026-01-09 10:56
  • 阅读:144
联系客服
源码代售 源码咨询 技术开发 联系客服
029-84538663
手机版

扫一扫进手机版
返回顶部