Skip to content

Session管理 原创

上一节我们实现了用户登录模块,当用户成功登录后,会给用户生成一个 token,后续的请求只要携带上 token 就可以操作 API 了。

只要 token 未过期,用户可以一直使用这个 token,就算进行了用户退出的操作,也没有特别好的办法直接修改 token 的过期时间。

为此,这里对登录进行改造:用户登录->生成 Token->存储 Session。登录过后的 API 都需要通过 Session 进行校验,退出登录则把后端保存的 session 删除掉。

通常情况下,我们会将 session 保存到缓存数据库中,比如 redis,我们这里也使用 Redis 来存储。

添加配置文件

(1)在 config.yaml 中添加以下配置信息

yaml
Cache:
  Type: redis
  Address: 127.0.0.1:6379
  Password: ""
  MaxConnect: 10
  Network: tcp
  Secret: "hawkeye"

(2)在 pkg/section.go 中增加缓存相关结构体

go
// CacheSettingS 缓存配置
type CacheSettingS struct {
	Type       string
	Address    string
	Password   string
	MaxConnect int
	Network    string
	Secret     string
}

(3)在 initialize/setting.go 中增加读取缓存配置

go
package initialize

import (
	"github.com/joker-bai/hawkeye/global"
	"github.com/joker-bai/hawkeye/pkg/setting"
)

// SetupSetting 初始化配置
func SetupSetting() error {
	s, err := setting.NewSetting()
	if err != nil {
		return err
	}
	......

	// 加载缓存配置
	if err := s.ReadSection("Cache", &global.CacheSetting); err != nil {
		return err
	}

	return nil
}

在 global/setting.go 中增加 CacheSetting 变量。

go
package global

import "github.com/joker-bai/hawkeye/pkg/setting"

var (
	ServerSetting   *setting.ServerSettingS
	DatabaseSetting *setting.DatabaseSettingS
	AppSetting      *setting.AppSettingS
	CacheSetting    *setting.CacheSettingS
)

初始化 Session

(1)在 initialize/session.go 中增加以下代码用于初始化 Session 存储。

go
package initialize

import (
	"github.com/gin-contrib/sessions/redis"
	"github.com/joker-bai/hawkeye/global"
)

func SetupSession() error {
	var err error
	global.SessionStore, err = redis.NewStore(
		global.CacheSetting.MaxConnect,
		global.CacheSetting.Network,
		global.CacheSetting.Address,
		global.CacheSetting.Password,
		[]byte(global.CacheSetting.Secret),
	)

	if err != nil {
		return err
	}
	return nil
}

在 global/session.go 中增加以下变量。

go
package global

import "github.com/gin-contrib/sessions"

var (
	SessionStore sessions.Store
)

(2)在 main.go 中增加初始化代码

go
func init() {
	......

	// 初始化Session
	if err := initialize.SetupSession(); err != nil {
		log.Fatalf("Failed to init session store, error: %s", err)
	}
}

修改登录操作

internal\app\controllers\api\v1\auth.go中增加存入 session 的操作,如下:

go
package v1

import (
	"encoding/json"
	"time"

	"github.com/gin-contrib/sessions"
	"github.com/gin-gonic/gin"
	"github.com/joker-bai/hawkeye/global"
	"github.com/joker-bai/hawkeye/internal/app/requests"
	"github.com/joker-bai/hawkeye/internal/app/services"
	"github.com/joker-bai/hawkeye/pkg/app"
	"github.com/joker-bai/hawkeye/pkg/errorcode"
	"github.com/joker-bai/hawkeye/pkg/jwt"
	"github.com/joker-bai/hawkeye/pkg/tools"
	"github.com/spf13/cast"
	"go.uber.org/zap"
)

type AuthController struct{}

// Create godoc
// @Summary 用户登录
// @Description 用户登录
// @Tags 认证管理
// @Produce json
// @Param body body requests.AuthLoginRequest true "body"
// @Success 200 {object} string "成功"
// @Failure 400 {object} errorcode.Error "请求错误"
// @Failure 500 {object} errorcode.Error "内部错误"
// @Router /api/v1/auth/login [post]
func (u *AuthController) Login(ctx *gin.Context) {
	......

	// 存入session
	sessionInfo := requests.LoginSessionInfo{
		Username:  param.Username,
		Token:     token,
		LoginTime: time.Now(),
	}

	sessionBty, err := json.Marshal(sessionInfo)
	if err != nil {
		return
	}
	session := sessions.Default(ctx)
	session.Set(tools.EncodeMD5(user.Username), string(sessionBty))
	_ = session.Save()

	response.ToResponse(gin.H{
		"data":  user,
		"token": token,
	})
}

然后在internal\app\requests\session.go中增加LoginSessionInfo结构体。

go
package requests

import "time"

type LoginSessionInfo struct {
	Username  string    `json:"username"`
	Token     string    `json:"token"`
	LoginTime time.Time `json:"login_time"`
}

pkg\tools\md5.go中增加 MD5 加密方法。

go
package tools

import (
	"crypto/md5"
	"encoding/hex"
)

// EncodeMD5 MD5加密
func EncodeMD5(value string) string {
	m := md5.New()
	m.Write([]byte(value))
	return hex.EncodeToString(m.Sum(nil))
}
最近更新