当前关注:用go设计开发一个自己的轻量级登录库/框架吧

时间:2023-05-06 18:42:29       来源:博客园
用go设计开发一个自己的轻量级登录库/框架吧

几乎每个项目都会有登录,退出等用户功能,而登录又不单仅仅是登录,我们要考虑很多东西。

token该怎么生成?生成什么样的?


(资料图片仅供参考)

是在Cookie存token还是请求头存token?读取的时候怎么读取?

允许同一个账号被多次登录吗?多次登录他们的token是一样的?还是不一样的?

登录也有可能分成管理员登录,用户登录等多种登录类型

我们要做的就是把这些东西封装到一起,然后能更方便的使用

而完成这些最难的就是如何设计架构了,其实要简单的封装一下并不难,本篇要讲的就是如何进行架构的设计了。

源码:weloe/token-go: a light login library (github.com)

Enforcer

我们可以抽象出一个供外部调用的执行器,它包括以下几个部分

token-go/enforcer.go at master · weloe/token-go (github.com)

type Enforcer struct {    // 从配置文件读取配置需要conf         string    // 登录类型loginType    stringconfig       config.TokenConfig    // 生成token的函数generateFunc model.GenerateTokenFunc    // 用于存储数据adapter      persist.Adapter    // 监听器watcher      persist.Watcher    // web上下文webCtx       ctx.Context    // 用于记录日志logger       log.Logger}

执行器的接口,包含供外部调用的方法

token-go/enforcer_interface.go at master · weloe/token-go · GitHub

var _ IEnforcer = &Enforcer{}type IEnforcer interface {    Login(id string) (string, error)LoginByModel(id string, loginModel *model.Login) (string, error)Logout() errorIsLogin() (bool, error)IsLoginById(id string) (bool, error)GetLoginId() (string, error)Replaced(id string, device string) errorKickout(id string, device string) errorGetRequestToken() stringSetType(t string)GetType() stringSetContext(ctx ctx.Context)GetAdapter() persist.AdapterSetAdapter(adapter persist.Adapter)SetWatcher(watcher persist.Watcher)SetLogger(logger log.Logger)EnableLog()IsLogEnable() boolGetSession(id string) *model.SessionSetSession(id string, session *model.Session, timeout int64) error}
Config

首先就是根据需求抽象出配置信息

一个是cookie的配置

token-go/cookie.go at master · weloe/token-go · GitHub

type CookieConfig struct {Domain   stringPath     stringSecure   boolHttpOnly boolSameSite string}

一个是token的配置

token-go/token.go at master · weloe/token-go · GitHub

type TokenConfig struct {   // TokenStyle   // uuid | uuid-simple | random-string32 | random-string64 | random-string128   TokenStyle string       TokenName   string   Timeout int64   // 允许多次登录   IsConcurrent bool   // 多次登录共享一个token   IsShare bool   // If (IsConcurrent == true && IsShare == false)才支持配置   // If IsConcurrent == -1, 不检查登录数量   MaxLoginCount int16   // 读取token的方式   IsReadBody   bool   IsReadHeader bool   IsReadCookie bool   // 是否把token写入响应头   IsWriteHeader bool   CookieConfig *CookieConfig}
Adapter

adapter是底层用来存储数据的结构,为了兼容不同的实现(不同的存储方式),设计成一个接口。

token-go/adapter.go at master · weloe/token-go · GitHub

type Adapter interface {// GetStr string operate string valueGetStr(key string) string// SetStr set store value and timeoutSetStr(key string, value string, timeout int64) error// UpdateStr only update valueUpdateStr(key string, value string) error// DeleteStr delete string valueDeleteStr(key string) error// GetStrTimeout get expireGetStrTimeout(key string) int64// UpdateStrTimeout update expire timeUpdateStrTimeout(key string, timeout int64) error// Get get interface{}Get(key string) interface{}// Set store interface{}Set(key string, value interface{}, timeout int64) error// Update only update interface{} valueUpdate(key string, value interface{}) error// Delete delete interface{} valueDelete(key string) error// GetTimeout get expireGetTimeout(key string) int64// UpdateTimeout update timeoutUpdateTimeout(key string, timeout int64) error}
Context

我们需要从请求读取token,可能也需要写出token,因此需要兼容不同的web上下文,我们需要设计一个Context接口

token-go/context.go at master · weloe/token-go · GitHub

type Context interface {Request() RequestResponse() ResponseReqStorage() ReqStorageMatchPath(pattern string, path string) boolIsValidContext() bool}
Watcher

监听器,用于在一些事件发生的时候进行一些其他操作。

token-go/watcher.go at master · weloe/token-go · GitHub

// Watcher event watchertype Watcher interface {// Login called after loginLogin(loginType string, id interface{}, tokenValue string, loginModel *model.Login)// Logout called after logoutLogout(loginType string, id interface{}, tokenValue string)}
Logger

Logger,用于记录日志,方便debug等等,需要设计成可以自由开启关闭。

token-go/logger.go at master · weloe/token-go · GitHub

type Logger interface {persist.Watcher// Enable turn on or offEnable(bool bool)// IsEnabled return if logger is enabledIsEnabled() bool}

到此,项目的大致的结构就设计完成,下一篇会讲讲本业务的具体实现

关键词: