欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Go?+?Gin實現(xiàn)雙Token管理員登錄的示例代碼

 更新時間:2025年07月15日 08:46:27   作者:Go?Dgg  
本文主要介紹了Go?+?Gin實現(xiàn)雙Token管理員登錄的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

一、為什么要做「雙 Token」

傳統(tǒng)單 Token(JWT)架構下,“續(xù)簽”與“強制失效” 是一對矛盾:

單 Token 痛點雙 Token 解法
Token 過期后需重新登錄,體驗差Access-Token 失效后,用 Refresh-Token 無感刷新
Token 一旦泄露,在有效期內(nèi)無法撤銷Refresh-Token 存 Redis,可一鍵踢人
續(xù)簽邏輯侵入業(yè)務代碼續(xù)簽、校驗、踢人全部封裝在 Auth 中間件

本文將用 Gin + GORM + Redis 帶你落地一套生產(chǎn)可用的「管理員雙 Token」登錄體系。

二、整體架構

┌────────────┐       ┌──────────────┐       ┌──────────┐
│   Web      │──────?│  Handler     │──────?│  Logic   │
└────────────┘       └──────────────┘       └──────────┘
         ▲                    ▲                      │
         │                    │                      ▼
         │            ┌──────────────┐       ┌──────────┐
         │            │  Response    │       │   Repo   │
         └────────────┘  Helper      │       └──────────┘
                                     │
                              Redis / MySQL
  • Handler 負責參數(shù)校驗、鑒權前置檢查
  • Logic 處理核心業(yè)務:登錄、刷新、退出、獲取用戶信息
  • Repo 封裝數(shù)據(jù)訪問:MySQL 查管理員、Redis 存 Refresh-Token
  • Response 統(tǒng)一封裝返回格式,避免樣板代碼

三、核心代碼走讀

3.1 路由層(Handler)

// NewAdminLoginHandler 管理員登錄
func NewAdminLoginHandler() gin.HandlerFunc {
    return func(c *gin.Context) {
        var req requests.AdminLoginReq
        if err := c.ShouldBindJSON(&req); err != nil {
            response.Fail(c, "參數(shù)不合法")
            return
        }

        repo := repositories.NewAdminLoginRepository(globals.DB, globals.RDB)
        logic := logics.NewAdminLoginLogic(repo)

        resp, err := logic.Login(c.Request.Context(), &req)
        if err != nil {
            response.Fail(c, fmt.Sprintf("登錄失敗: %v", err))
            return
        }
        response.OK(c, "登錄成功", resp)
    }
}
  • 只做「綁定參數(shù) + 調(diào)用邏輯 + 包裝返回」
  • 不摻雜任何業(yè)務判斷,保持 單一職責

3.2 業(yè)務層(Logic)

3.2.1 登錄

func (l *AdminLoginLogic) Login(ctx context.Context, req *requests.AdminLoginReq) (*responses.AdminLoginResp, error) {
    admin, err := l.findAdminByAccount(ctx, req.Account)
    if err != nil || admin == nil {
        return nil, errors.New("賬號不存在")
    }
    if admin.Status != 1 {
        return nil, errors.New("賬號已被禁用")
    }
    if !usersignutil.CheckPasswordHash(req.Password, admin.Password) {
        return nil, errors.New("密碼錯誤")
    }

    // 更新最后登錄時間
    _ = l.adminRepo.UpdateLastLoginTime(ctx, admin.ID)

    // 生成雙 Token
    return l.generateTokensAndBuildResponse(ctx, admin)
}

3.2.2 生成雙 Token

func (l *AdminLoginLogic) generateTokensAndBuildResponse(
    ctx context.Context,
    admin *models.Admin,
) (*responses.AdminLoginResp, error) {

    accessToken, _ := usersignutil.GenerateAccessToken(admin.ID)
    refreshToken, _ := usersignutil.GenerateRefreshToken(admin.ID)

    // 保存 Refresh-Token 到 Redis,設置過期時間
    err := l.adminRepo.SaveRefreshToken(
        ctx,
        admin.ID,
        refreshToken,
        globals.AppConfig.JWT.RefreshTokenExpiry,
    )
    if err != nil {
        // 記錄日志但不阻斷登錄
        globals.Log.Error("SaveRefreshToken err:", err)
    }

    resp := (&responses.AdminLoginResp{}).ToResponse(admin)
    resp.AccessToken = accessToken
    resp.RefreshToken = refreshToken
    return resp, nil
}

3.2.3 獲取管理員信息

func (l *AdminLoginLogic) GetAdminInfo(ctx context.Context, adminID uint) (*responses.AdminInfoResp, error) {
    admin, err := l.adminRepo.FindByIDWithDetails(ctx, adminID)
    if err != nil || admin == nil {
        return nil, errors.New("管理員不存在")
    }
    if admin.Status != 1 {
        return nil, errors.New("賬號已被禁用")
    }
    return (&responses.AdminInfoResp{}).ToResponse(admin), nil
}

3.2.4 登出

func (l *AdminLoginLogic) Logout(ctx context.Context, adminID uint) error {
    return l.adminRepo.DeleteRefreshToken(ctx, adminID)
}

3.3 數(shù)據(jù)訪問層(Repo)

僅展示關鍵函數(shù),完整代碼已在文章開頭給出。

  • FindByPhone / FindByAccountID / FindByIDWithDetails
    利用 GORM 的 Preload 一把連表查,減少 N+1

  • SaveRefreshToken / DeleteRefreshToken
    使用 admin:refresh_token:{id} 作為 Redis Key,天然支持「單設備登錄」或「多端互踢」

四、如何無感刷新 Access-Token

前端收到 401 Unauthorized 后,攜帶 Refresh-Token 調(diào) /admin/refresh

// 偽代碼(Handler 略)
refreshToken := c.GetHeader("X-Refresh-Token")
adminID, err := usersignutil.ParseRefreshToken(refreshToken)
if err != nil { /* 無效 Refresh-Token */ }

// 與 Redis 比對
saved, _ := repo.GetRefreshToken(ctx, adminID)
if saved != refreshToken { /* 已被踢出 */ }

// 重新頒發(fā)
newAccess, _ := usersignutil.GenerateAccessToken(adminID)

五、安全細節(jié)

細節(jié)實現(xiàn)
密碼加密bcrypt 哈希,不可逆
Token 簽名使用獨立 jwtSecret,區(qū)分 Access/Refresh
Refresh-Token 存儲Redis + TTL,支持熱踢人
SQL 注入GORM 占位符自動防注入
并發(fā)登錄Redis Key 覆蓋即可實現(xiàn)「后者踢前者」

六、總結

本文用 200 行核心代碼展示了:

  1. 分層架構:Handler → Logic → Repo
  2. 雙 Token:Access-Token(短)+ Refresh-Token(長)
  3. 統(tǒng)一響應:封裝 response.OK / Fail 消除樣板
  4. 安全退出:Redis 刪除 Refresh-Token 即踢人

到此這篇關于Go + Gin實現(xiàn)雙Token管理員登錄的示例代碼的文章就介紹到這了,更多相關Go Gin 雙Token管理員登錄內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家! 

相關文章

  • golang協(xié)程與線程區(qū)別簡要介紹

    golang協(xié)程與線程區(qū)別簡要介紹

    這篇文章主要介紹了golang協(xié)程與線程區(qū)別簡要介紹,進程是操作系統(tǒng)資源分配的基本單位,是程序運行的實例,線程是操作系統(tǒng)調(diào)度到CPU中執(zhí)行的基本單位
    2022-06-06
  • go語言規(guī)范RESTful?API業(yè)務錯誤處理

    go語言規(guī)范RESTful?API業(yè)務錯誤處理

    這篇文章主要為大家介紹了go語言規(guī)范RESTful?API業(yè)務錯誤處理方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-03-03
  • gtoken替換jwt實現(xiàn)sso登錄的排雷避坑

    gtoken替換jwt實現(xiàn)sso登錄的排雷避坑

    這篇文章主要為大家介紹了gtoken替換jwt實現(xiàn)sso登錄的排雷避坑,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-06-06
  • Golang設計模式工廠模式實戰(zhàn)寫法示例詳解

    Golang設計模式工廠模式實戰(zhàn)寫法示例詳解

    這篇文章主要為大家介紹了Golang 工廠模式實戰(zhàn)寫法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08
  • Go習慣用法(多值賦值短變量聲明賦值簡寫模式)基礎實例

    Go習慣用法(多值賦值短變量聲明賦值簡寫模式)基礎實例

    本文為大家介紹了Go習慣用法(多值賦值,短變量聲明和賦值,簡寫模式、多值返回函數(shù)、comma,ok 表達式、傳值規(guī)則)的基礎實例,幫大家鞏固扎實Go語言基礎
    2024-01-01
  • Go java 算法之括號生成示例詳解

    Go java 算法之括號生成示例詳解

    這篇文章主要為大家介紹了Go java 算法之括號生成示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08
  • Golang 實現(xiàn)超大文件讀取的兩種方法

    Golang 實現(xiàn)超大文件讀取的兩種方法

    這篇文章主要介紹了Golang 實現(xiàn)超大文件讀取的兩種方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • golang內(nèi)置函數(shù)len的小技巧

    golang內(nèi)置函數(shù)len的小技巧

    len是很常用的內(nèi)置函數(shù),可以測量字符串、slice、array、channel以及map的長度/元素個數(shù)。本文就來介紹一下其他小技巧,感興趣的可以了解一下
    2021-07-07
  • Go設計模式之狀態(tài)模式圖文詳解

    Go設計模式之狀態(tài)模式圖文詳解

    狀態(tài)模式是一種行為設計模式, 讓你能在一個對象的內(nèi)部狀態(tài)變化時改變其行為, 使其看上去就像改變了自身所屬的類一樣,本文將通過一些圖片來給大家詳細的介紹一下Go的狀態(tài)模式,需要的朋友可以參考下
    2023-08-08
  • go語言切片去重的3種方式

    go語言切片去重的3種方式

    go語言中的切片是使用非常頻繁的一個數(shù)據(jù)結構,本文主要介紹了go語言切片去重的3種方式,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2024-08-08

最新評論