几乎每个项目都会有登录,退出等用户功能,而登录又不单仅仅是登录,我们要考虑很多东西。
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}
Adapteradapter是底层用来存储数据的结构,为了兼容不同的实现(不同的存储方式),设计成一个接口。
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)}
LoggerLogger,用于记录日志,方便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}
到此,项目的大致的结构就设计完成,下一篇会讲讲本业务的具体实现
关键词: