You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Golang+Cobra开发CLI应用:如何实现登录会话持久化(仿Azure CLI)

基于Golang+Cobra实现Azure CLI风格的会话管理方案

核心逻辑

  • 登录命令完成认证后,将非敏感的会话凭证(如认证token、服务器地址、会话创建时间等)加密存储到本地文件(禁止明文存储密码)
  • 非登录类命令执行前,先检查本地会话文件:
    • 若文件存在且凭证有效(未过期、匹配当前系统重启状态),则自动加载复用会话
    • 若文件不存在或凭证无效,强制要求用户先执行登录命令
  • 系统重启后,会话凭证失效,需重新登录

具体实现步骤

1. 定义会话存储结构

先定义结构体保存会话核心信息,包含重启检测字段:

type Session struct {
    ServerURL      string    `json:"server_url"`
    AuthToken      string    `json:"auth_token"`
    ExpiresAt      time.Time `json:"expires_at"`
    SystemBootTime int64     `json:"system_boot_time"` // 用于检测系统是否重启
}

2. 实现登录命令(Cobra)

在login命令的Run函数中完成认证,将会话凭证加密写入本地文件:

var loginCmd = &cobra.Command{
    Use:   "login",
    Short: "Authenticate with the server",
    RunE: func(cmd *cobra.Command, args []string) error {
        username, _ := cmd.Flags().GetString("username")
        password, _ := cmd.Flags().GetString("password")
        server, _ := cmd.Flags().GetString("server")

        // 调用自定义认证接口,获取token和过期时间
        authToken, expiresAt, err := authenticate(username, password, server)
        if err != nil {
            return err
        }

        // 获取系统启动时间(用于后续重启检测)
        bootTime, err := getSystemBootTime()
        if err != nil {
            return err
        }

        // 构造会话对象
        session := Session{
            ServerURL:      server,
            AuthToken:      authToken,
            ExpiresAt:      expiresAt,
            SystemBootTime: bootTime,
        }

        // 加密会话并写入本地文件(示例路径:~/.app_session)
        return saveEncryptedSession(session)
    },
}

注意:加密可采用AES算法,密钥可结合用户本地环境信息生成(如用户目录路径、机器UUID),避免明文泄露凭证

3. 会话加载与验证逻辑

编写公共函数,供非登录命令调用以验证会话有效性:

func loadValidSession() (*Session, error) {
    // 读取并解密本地会话文件
    session, err := loadEncryptedSession()
    if err != nil {
        return nil, fmt.Errorf("未登录,请先执行 `app login` 命令")
    }

    // 检查token是否过期
    if time.Now().After(session.ExpiresAt) {
        return nil, fmt.Errorf("会话已过期,请重新登录")
    }

    // 检查系统是否重启(对比当前与会话记录的启动时间)
    currentBootTime, err := getSystemBootTime()
    if err != nil {
        return nil, err
    }
    if currentBootTime != session.SystemBootTime {
        return nil, fmt.Errorf("系统已重启,请重新登录")
    }

    return session, nil
}

getSystemBootTime可通过读取系统文件实现:Linux读取/proc/stat,Windows调用WMI接口,macOS读取sysctl kern.boottime。

4. 改造非登录命令(如create user)

在需要复用会话的命令中,先加载验证会话,再初始化客户端执行逻辑:

var createUserCmd = &cobra.Command{
    Use:   "create user",
    Short: "创建新用户",
    RunE: func(cmd *cobra.Command, args []string) error {
        // 加载并验证会话
        session, err := loadValidSession()
        if err != nil {
            return err
        }

        // 用会话凭证初始化客户端
        client, err := initClient(session.ServerURL, session.AuthToken)
        if err != nil {
            return err
        }

        // 执行创建用户逻辑
        username, _ := cmd.Flags().GetString("username")
        return client.CreateUser(username)
    },
}

5. 主动注销会话

添加logout命令,支持用户主动删除本地会话文件:

var logoutCmd = &cobra.Command{
    Use:   "logout",
    Short: "结束当前会话",
    RunE: func(cmd *cobra.Command, args []string) error {
        return deleteSessionFile()
    },
}

关键细节

  • 会话文件存储位置:推荐存放在用户专属配置目录,如Linux的~/.config/app/session、Windows的%APPDATA%/app/session、macOS的~/Library/Application Support/app/session
  • 过期时间处理:认证时同步获取token过期时间,每次验证时主动检查,可提前提醒用户重新登录
  • 异常场景处理:会话文件损坏、凭证篡改时,直接触发重新登录流程

内容的提问来源于stack exchange,提问作者Varun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 19:40:34