token-go 一个轻量级登录权限库

weloe · 2023-05-13 15:42:45 · 2302 次点击    
这是一个分享于 2023-05-13 15:42:45 的资源,其中的信息可能已经有所发展或是发生改变。

Github仓库: https://github.com/weloe/token-go

token-go 致力于解决登录相关的问题,使用它可以更方便快速搭建一个项目中的用户登录相关模块,一键解决用户登录管理相关的问题。 例如:同一用户只能登录一次,同一用户多次登录多token,同一用户多次登录共享一个token,不同token生成方式,踢下线等等。

安装

go get github.com/weloe/token-go

使用默认配置

import (
    "fmt"
    tokenGo "github.com/weloe/token-go"
    "log"
    "net/http"
)

var enforcer *tokenGo.Enforcer

func main() {
    var err error
    // use default adapter
    adapter := tokenGo.NewDefaultAdapter()
    enforcer, err = tokenGo.NewEnforcer(adapter)
    // enable logger
    enforcer.EnableLog()
    if err != nil {
        log.Fatal(err)
    }

    http.HandleFunc("/user/login", Login)
    http.HandleFunc("/user/isLogin", IsLogin)

    log.Fatal(http.ListenAndServe(":8081", nil))
}

func Login(w http.ResponseWriter, req *http.Request) {
    token, err := enforcer.Login("1", tokenGo.NewHttpContext(req, w))
    if err != nil {
        fmt.Fprintf(w, "Login error: %s\n", err)
    }
    fmt.Fprintf(w, "token: %s\n", token)
}

func IsLogin(w http.ResponseWriter, req *http.Request) {
    login, err := enforcer.IsLogin(tokenGo.NewHttpContext(req, w))
    if err != nil {
        fmt.Fprintf(w, "IsLogin() = %v: %v", login, err)
    }
    fmt.Fprintf(w, "IsLogin() = %v", login)
}

自定义配置

同一用户只能登录一次:IsConcurrent = false && IsShare = false 同一用户多次登录共享一个token:IsConcurrent = true && IsShare = false 同一用户多次登录多token:IsConcurrent = true && IsShare = true

import (
    "fmt"
    tokenGo "github.com/weloe/token-go"
    "github.com/weloe/token-go/config"
    "log"
    "net/http"
)

var enforcer *tokenGo.Enforcer

func main() {
    var err error
    // use default adapter
    adapter := tokenGo.NewDefaultAdapter()
    tokenConfig := &config.TokenConfig{
        TokenName:     "uuid",
        Timeout:       60,
        IsReadCookie:  true,
        IsReadHeader:  true,
        IsReadBody:    false,
        IsConcurrent:  true,
        IsShare:       true,
        MaxLoginCount: -1,
    }
    enforcer, err = tokenGo.NewEnforcer(adapter, tokenConfig)
}

也可以从文件中读取配置信息

TokenConfig:
  tokenStyle: uuid
  tokenName: myTokenName
  timeout: 2592000
  dataRefreshPeriod: 30
  isConcurrent: true
  isShare: true
  maxLoginCount: 12
  isReadBody: true
  isReadHeader: true
  isReadCookie: true
  isWriteHeader: false
enforcer, err = tokenGo.NewEnforcer(adapter, filepath)

权限校验

此外还提供简单的权限校验

type ACL interface {
    GetPermission(id string) []string
}
type RBAC interface {
   GetRole(id string) []string
}

实现这两个接口中的任意一个并调用enforcer.SetAuth(model) 之后就可以使用这两个api进行权限校验

    // 实现RBAC接口后可使用
    CheckRole(ctx ctx.Context, role string) error
    // 实现ACL接口后可使用
    CheckPermission(ctx ctx.Context, permission string) error

使用示例

type MockRbacAuth struct {
}

func (m *MockRbacAuth) GetRole(id string) []string {
    var arr = make([]string, 2)
    arr[1] = "user"
    return arr
}

type MockAclAuth struct {
}

func (m *MockAclAuth) GetPermission(id string) []string {
    var arr = make([]string, 2)
    arr[1] = "user::get"
    return arr
}

func TestEnforcer_CheckRole(t *testing.T) {
    err, enforcer, ctx := NewTestEnforcer(t)
    if err != nil {
        t.Errorf("NewTestEnforcer() failed: %v", err)
    }
    m := &MockRbacAuth{}
    enforcer.SetAuth(m)
    loginModel := model.DefaultLoginModel()
    loginModel.Token = "233"
    _, err = enforcer.LoginByModel("id", loginModel, ctx)
    if err != nil {
        t.Errorf("Login() failed: %v", err)
    }

    err = enforcer.CheckRole(ctx, "user")
    if err != nil {
        t.Errorf("CheckRole() failed: %v", err)
    }

    err = enforcer.CheckPermission(ctx, "user::get")
    if err == nil {
        t.Errorf("CheckRole() failed")
    }
    t.Logf("CheckPermission() return %v", err)
}

Api

    // 登录
    Login(id string, ctx ctx.Context) (string, error)
    // 指定参数登录
    LoginByModel(id string, loginModel *model.Login, ctx ctx.Context) (string, error)
    // 退出
    Logout(ctx ctx.Context) error
    // 判断是否登录
    IsLogin(ctx ctx.Context) (bool, error)
    IsLoginById(id string) (bool, error)
    // 获得当前登录的id
    GetLoginId(ctx ctx.Context) (string, error)
    // 获取账号的登录数量
    GetLoginCount(id string) int
    // 模拟顶其他账号下线
    Replaced(id string, device string) error
    // 把其他账号踢下线
    Kickout(id string, device string) error
    // 获取当前的token
    GetRequestToken(ctx ctx.Context) string
    // 添加自定义的token生成方法
    AddTokenGenerateFun(tokenStyle string, f model.GenerateFunc) error
    //检查是否登录
    CheckLogin(ctx ctx.Context) error

    SetAuth(manager interface{})
    // 检查是否有该角色
    CheckRole(ctx ctx.Context, role string) error
    // 检查是否有该权限
    CheckPermission(ctx ctx.Context, permission string) error

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

2302 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传