登录鉴权与 Token 管理

一、前言:为什么选择 TSRPC 做登录鉴权?

  • TSRPC 核心优势:类型安全、前后端一体化、无冗余编码
  • 登录鉴权场景适配性:Token 机制与 TSRPC 接口拦截的契合度

二、前期准备:环境搭建与基础配置

    1. 技术栈选型说明
    • 前端:Vue
    • 后端:Node.js + TSRPC
    • 数据库:MongoDB(存储用户信息与 Token)
    • 依赖:jsonwebtoken(生成 Token)
    1. TSRPC 前后端初始化
    • 服务端项目创建与接口基础配置
    • 前端项目创建与 TSRPC 客户端连接
    • 前后端类型同步(TSRPC 核心特性,确保数据格式一致)
    1. 数据库表设计
    • 用户表:存储用户名、密码等基础信息
    • Token 表:存储用户 ID、Token 字符串、过期时间等

三、核心实现:登录流程全解析

  • 3.1 第一步:前端登录表单实现与数据提交
    • 登录表单组件开发(用户名、密码输入框 + 提交按钮)
    • 表单验证:非空校验、格式合法性校验
    • TSRPC 客户端调用登录接口(apiLogin),提交用户名密码
  • 3.2 第二步:后端 apiLogin 接口实现(免鉴权配置)
    • TSRPC 接口定义:请求参数类型(用户名、密码)与响应类型(Token)
    • 免鉴权配置:通过 TSRPC 中间件排除 apiLogin 接口,无需 Token 即可访问
    • 后端校验逻辑,查询数据库,验证用户名是否存在,验证密码是否正确
  • 3.3 第三步:Token 生成与数据库存储
    • 基于 jsonwebtoken 生成 Token:传入用户 ID 等核心信息,设置过期时间
    • Token 存储到数据库:关联用户 ID,记录生成时间与过期时间
    • 后端响应结果:将生成的 Token 返回给前端

四、关键拓展:全局接口鉴权实现

  • 4.1 前端全局请求拦截

    • 响应拦截

      TypeScript 复制代码
      const TokenStorageKey = 'tsrpc-token'
      // 响应拦截器
      client.flows.preApiReturnFlow.push((v) => {
        if (v.return.isSucc) {
          if (v.return.res.__ssoToken) {
            localStorage.setItem(TokenStorageKey, JSON.stringify(v.return.res.__ssoToken))
          }
        } else {
          const errorMsg = v.return.err.message
          // 解析错误码
          if (errorMsg.startsWith('NEED_LOGIN:')) {
            ElMessage.error('请先登录')
            router.push('/login')
          } else {
            ElMessage.error(errorMsg.replace(/^[\w_]+:\s*/, '')) // 移除错误码前缀
          }
        }
      
        return v
      })
    • 请求拦截

      TypeScript 复制代码
      client.flows.preCallApiFlow.push((v) => {
        let tokenStr = localStorage.getItem(TokenStorageKey)
        v.req.__ssoToken = tokenStr ? JSON.parse(tokenStr) : undefined
        return v
      })
  • 4.2 后端全局鉴权中间件:验证 Token 合法性

    • 拦截器截获接口中带的 __ssoToken

      TypeScript 复制代码
      /**
       * 在 API 调用前解析当前用户身份
       * @param server HttpServer
       */
      export function parseCurrentUser(server: HttpServer) {
        // API 调用前的拦截器 
        server.flows.preApiCallFlow.push(async (call) => {
          let req = call.req as BaseRequest
          if (req.__ssoToken) {
            // 验证并解析 SSO Token
            const user = await UserService.verifyToken(req.__ssoToken)
            if (user) {
              call.currentUser = user
            }
          }
          return call
        })
      }
    • 验证是用户身份

      复制代码
        ```TypeScript
        /**
         * 验证用户身份
         * @param server HttpServer
         */
        export function enableAuthentication(server: HttpServer) {
          // API 调用前的拦截器
          server.flows.preApiCallFlow.push((call) => {
            let conf: BaseConf | undefined = call.service.conf
        
            // 默认需要登录,除非明确设置 needLogin: false
            if (conf?.needLogin !== false && !call.currentUser) {
              call.error('NEED_LOGIN: 请先登录')
              return undefined
            }
        
            return call
          })
        }
        ```
    • 校验结果处理:通过则放行,不通过则call.error

五、补充功能:Token 注销与过期处理

    1. 退出登录功能:前端清除本地 Token + 后端删除数据库中对应 Token 记录
    1. Token 过期处理:
    • 前端:拦截器中检测到以 NEED_LOGIN: 开头的消息,跳转到登录页
    TypeScript 复制代码
    const errorMsg = v.return.err.message
    // 解析错误码
    if (errorMsg.startsWith('NEED_LOGIN:')) {
      ElMessage.error('请先登录')
      router.push('/login')
    } else {
      ElMessage.error(errorMsg.replace(/^[\w_]+:\s*/, '')) // 移除错误码前缀
    }
    1. 数据库基本设计,两个表,token 和 user 两个表
    TypeScript 复制代码
    export interface db_Token {
      _id?: ObjectId
      userId: string
      token: string
      createdAt?: Date
      expiresAt?: Date
    }
    TypeScript 复制代码
    export interface db_User {
      _id: ObjectId | string;
      username: string;  // 用户名
      password: string; // 密码
      thumb?: string;  // 头像
      state: number;  // 账户状态
      updatedAt?: Date | string
      createdAt?: Date | string
    }

六:部分截图


gitee 开源地址:https://gitee.com/liucenter/tsrpc-manage-system

相关推荐
嘿嘿-666 小时前
Cherry Studio 接入ChatGpt:GPT-5.6 Sol 文本测试与 GPT-Image-2 出图教程
人工智能·gpt·ai·chatgpt·node.js·ai编程
大牧师6 小时前
TypeORM 学习教程
数据库·sql·学习·node.js·orm·nest.js·typeorm
逻辑08 小时前
安装 Claude Code 完整指南(用户级 Node.js 环境)
node.js·claude code
Wang's Blog8 小时前
Vibe Coding一人即团队系列54:云服务器 Node.js 与 MySQL 9 环境搭建及配置指南
服务器·人工智能·mysql·node.js
FungLeo8 小时前
成为全栈·Node 后端篇·结构化日志与请求链路追踪
node.js·结构化日志·成为全栈·请求链路
Flynt12 小时前
NestJS 12升级踩坑:从Webpack到Rspack,我折腾了一整个周末
typescript·node.js·nestjs
FungLeo1 天前
成为全栈·Node 后端篇·配置管理:环境变量、多环境与密钥安全
node.js·环境变量·多环境配置·密钥安全
FungLeo1 天前
成为全栈·Node 后端篇·错误处理:异常分层与全局捕获
node.js·错误处理·异常分层·全局捕获·成为全栈
百万运营Pro1 天前
用 Astro + Supabase 从零构建全网盘聚合搜索引擎:PGroonga 中文检索实战
搜索引擎·前端框架·node.js·个人开发·学习方法·ai编程·资源分享
小婉2 天前
我用 Next.js + React Flow 从零搭建了一个可视化 AI 工作流编排平台
前端·人工智能·node.js