乐趣区

关于session:工具库系列之分布式-Session-Golang库

分布式 Session Golang 库





English README

反对多个 Web 服务共享 Session 令牌 token,这样能够实现多个服务间共享状态。

当初 Session 令牌能够存储在:

  1. 单机模式的 Redis。
  2. 哨兵模式的 Redis。什么是哨兵,咱们晓得 Redis 有主从复制的性能,主服务器提供服务,从服务器作为数据同步来进行备份。当主服务器挂掉时,哨兵能够将从服务器晋升到主角色。

如何应用

很简略,执行:

go get -v github.com/hunterhug/gosession

外围 API:

// 分布式 Session 治理
// Token
type TokenManage interface {SetToken(id string, tokenValidTimes int64) (token string, err error)                               // 设置令牌,传入用户 ID 和令牌过期工夫,单位秒,会生成一个 Token 返回,登录时能够调用
    RefreshToken(token string, tokenValidTimes int64) error                                            // 刷新令牌过期工夫,令牌会持续存活
    DeleteToken(token string) error                                                                    // 删除令牌,退出登录时能够调用
    CheckToken(token string) (user *User, exist bool, err error)                                       // 查看令牌是否存在(查看会话是否存在)CheckTokenOrUpdateUser(token string, userInfoValidTimes int64) (user *User, exist bool, err error) // 查看令牌是否存在(查看会话是否存在),并缓存用户信息,如果有的话,默认不更新用户信息,可设置 ConfigGetUserInfoFunc
    ListUserToken(id string) ([]string, error)                                                         // 列出用户的所有令牌
    DeleteUserToken(id string) error                                                                   // 删除用户的所有令牌
    RefreshUser(id []string, userInfoValidTimes int64) error                                           // 批量刷新用户信息,如果有的话,默认不缓存用户信息,可设置 ConfigGetUserInfoFunc
    DeleteUser(id string) error                                                                        // 删除用户信息,默认不缓存用户信息,可设置 ConfigGetUserInfoFunc
    AddUser(id string, userInfoValidTimes int64) (user *User, exist bool, err error)                   // 新增缓存用户信息,默认不缓存用户信息,可设置 ConfigGetUserInfoFunc
    ConfigTokenKeyPrefix(tokenKey string) TokenManage                                                  // 设置令牌前缀
    ConfigUserKeyPrefix(userKey string) TokenManage                                                    // 设置用户信息前缀,默认不缓存用户信息,可设置 ConfigGetUserInfoFunc
    ConfigDefaultExpireTime(second int64) TokenManage                                                  // 设置令牌默认过期工夫
    ConfigGetUserInfoFunc(fn GetUserInfoFunc) TokenManage                                              // 设置获取用户信息的函数
    SetSingleMode() TokenManage                                                                        // 是否独占单点登录,新生成一个令牌,会挤掉其余令牌}

// 用户信息,存 token 在缓存里,比方 redis
// 如果有设置 ConfigGetUserInfoFunc(fn GetUserInfoFunc),那么同时也会缓存该用户信息,你能够在函数 type GetUserInfoFunc func(id string) (*User, error) 里将业务用户信息存入 Detail 并返回。type User struct {
    Id                  string      `json:"id"`     // 用户标记,惟一
    TokenRemainLiveTime int64       `json:"-"`      // token 还有多少秒就过期了
    Detail              interface{} `json:"detail"` // 能够寄存用户业务信息}

例子:

package main

import (
    "fmt"
    "github.com/hunterhug/gosession"
    "time"
)

func main() {
    // 1. 配置 Redis,目前反对单机和哨兵
    redisHost := "127.0.0.1:6379"
    redisDb := 0
    redisPass := "hunterhug" // Redis 个别是没有明码的,能够留空
    redisConfig := gosession.NewRedisSessionSingleModeConfig(redisHost, redisDb, redisPass)
    // or
    //gosession.NewRedisSessionSentinelModeConfig()

    // 2. 连贯 Session 管理器
    tokenManage, err := gosession.NewRedisSession(redisConfig)
    if err != nil {fmt.Println(err.Error())
        return
    }

    // 3. 配置 Session 管理器,比方 Token 600 秒过期,以及 token 和用户信息 key 的前缀
    tokenManage.ConfigDefaultExpireTime(600)
    tokenManage.ConfigUserKeyPrefix("go-user")
    tokenManage.ConfigTokenKeyPrefix("go-token")
    fn := func(id string) (user *gosession.User, err error) {
        return &gosession.User{
            Id:     id,
            Detail: map[string]string{"detail": id},
        }, nil
    } // 能够设置获取用户信息的函数,如果用户没有缓存,会从该函数加载后存进 redis,容许 nil
    tokenManage.ConfigGetUserInfoFunc(fn)
    //tokenManage.SetSingleMode() // 你能够设置单点的 token

    // 4. 为某用户设置 Token
    id := "000001"
    var tokenExpireTimeAlone int64 = 2 // token 过期工夫设置 2 秒

    token, err := tokenManage.SetToken(id, tokenExpireTimeAlone)
    if err != nil {fmt.Println("set token err:", err.Error())
        return
    }

    fmt.Println("token:", token)

    // 能够设置多个令牌
    tokenManage.SetToken(id, 100)
    tokenManage.SetToken(id, 100)
    tokenManage.SetToken(id, 100)

    // 5. 列出用户所有的令牌
    tokenList, err := tokenManage.ListUserToken(id)
    if err != nil {fmt.Println("list token err:", err.Error())
        return
    }
    fmt.Println("list token:", tokenList)

    // 6. 查看 token 是否存在,存在会返回用户信息
    var userExpireTimeAlone int64 = 10 // 如果用户不存在并且 ConfigGetUserInfoFunc!=nil,将会加载用户信息,从新放入 redis
    u, exist, err := tokenManage.CheckTokenOrUpdateUser(token, userExpireTimeAlone)
    if err != nil {fmt.Println("check token err:", err.Error())
        return
    }

    fmt.Printf("check token:%#v, %#v,%#v\n", token, u, exist)

    err = tokenManage.RefreshToken(token, 5)
    if err != nil {fmt.Println("refresh token err:", err.Error())
        return
    }

    u, exist, err = tokenManage.CheckTokenOrUpdateUser(token, userExpireTimeAlone)
    if err != nil {fmt.Println("after refresh check token err:", err.Error())
        return
    }

    fmt.Printf("after refresh token:%#v, %#v,%#v\n", token, u, exist)

    // 7. 睡眠一下,看 token 是不是生效了
    time.Sleep(10 * time.Second)
    u, exist, err = tokenManage.CheckTokenOrUpdateUser(token, userExpireTimeAlone)
    if err != nil {fmt.Println("sleep check token err:", err.Error())
        return
    }

    fmt.Printf("sleep check token:%#v, %#v,%#v\n", token, u, exist)

    // 能够删除用户的所有令牌
    tokenList, err = tokenManage.ListUserToken(id)
    if err != nil {fmt.Println("sleep list token err:", err.Error())
        return
    }
    fmt.Println("sleep token:", tokenList)

    err = tokenManage.DeleteUserToken(id)
    if err != nil {fmt.Println("delete user token err:", err.Error())
        return
    }

    tokenList, err = tokenManage.ListUserToken(id)
    if err != nil {fmt.Println("after delete user token list err:", err.Error())
        return
    }
    fmt.Println("after delete user token list:", tokenList)
}

License

Copyright [2019-2021] [github.com/hunterhug]

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
退出移动版