设为首页 加入收藏

TOP

用go设计开发一个自己的轻量级登录库/框架吧(业务篇)(一)
2023-07-23 13:28:04 】 浏览:74
Tags:计开发

用go设计开发一个自己的轻量级登录库/框架吧(业务篇)

本篇会讲讲框架的登录业务的实现。实现三种登录模式:

  • 同一用户只能登录一次
  • 同一用户多次登录多token
  • 同一用户多次登录共享一个token

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

存储结构

首先从我们要考虑是底层该怎么存储登录信息来去达成这三种登录模式

  • 同一用户只能登录一次
  • 同一用户多次登录多token
  • 同一用户多次登录共享一个token

我们不能使用无状态token模式,要有状态,在后端存储会话信息才能达成想要实现的一些逻辑,因此,存储会话信息是必要的。

对于每个请求,我们会存储一个token-loginId的k-v结构。

对于整个会话,我们会存储一个loginId-session的k-v结构。

基于这个存储结构我们就可以方便的实现这三种模式。

Session结构体

session包括了多个tokenValue,这就是我们用来实现同一用户多次登录多token,或者同一用户多次登录共享一个token的关键点

type TokenSign struct {
   Value  string
   Device string
}

type Session struct {
   Id            string
   TokenSignList *list.List
}

总之,我们实现的业务将基于这两种k-v结构

功能实现

源码:https://github.com/weloe/token-go/blob/f58ba4d93f0f012972bf6a35b9127229b5c328fe/enforcer.go#L167

我们再来梳理一些功能和配置的对应关系

同一用户只能登录一次:IsConcurrent == false

同一用户多次登录多token: IsConcurrent == true && IsShare == false这时候配置MaxLoginCount才生效

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

接着我们再讲讲登录的具体流程:

我们大致将它分为几个阶段:

  • 生成token

  • 生成session

  • 存储token-id , id-session

  • 返回信息

  • 调用watcher和logger

  • 检测登录人数

生成token

https://github.com/weloe/token-go/blob/f58ba4d93f0f012972bf6a35b9127229b5c328fe/enforcer_internal_api.go#L12

生成token的时候,我们要判断他是否是可多次登录,也就是isConcurrent是否为false

如果可多次登录并且共享token即IsConcurrent == true && IsShare == true,就判断能否复用之前的token

这里我们还允许用户自定义token。

loginModel *model.Login是为了支持自定义这几个参数

type model.Login struct {
	Device          string
	IsLastingCookie bool
	Timeout         int64
	Token           string
	IsWriteHeader   bool
}
// createLoginToken create by config.TokenConfig and model.Login
func (e *Enforcer) createLoginToken(id string, loginModel *model.Login) (string, error) {
	tokenConfig := e.config
	var tokenValue string
	var err error
	// if isConcurrent is false,
	if !tokenConfig.IsConcurrent {
		err = e.Replaced(id, loginModel.Device)
		if err != nil {
			return "", err
		}
	}

	// if loginModel set token, return directly
	if loginModel.Token != "" {
		return loginModel.Token, nil
	}

	// if share token
	if tokenConfig.IsConcurrent && tokenConfig.IsShare {
		// reuse the previous token.
		if v := e.GetSession(id); v != nil {
			tokenValue = v.GetLastTokenByDevice(loginModel.Device)
			if tokenValue != "" {
				return tokenValue, nil
			}

		}
	}

	// create new token
	tokenValue, err = e.generateFunc.Exec(tokenConfig.TokenStyle)
	if err != nil {
		return "", err
	}

	return tokenValue, nil
}

生成session

https://github.com/weloe/token-go/blob/f58ba4d93f0f012972bf6a35b9127229b5c328fe/enforcer.go#L183

先判断是否已经存在session,如果不存在需要先创建,避免空指针

	// add tokenSign
	if session = e.GetSession(id); session == nil {
		session = model.NewSession(e.spliceSessionKey(id), "account-session", id)
	}
	session.AddTokenSign(&model.TokenSign{
		Value:  tokenValue,
		Device: loginModel.Device,
	})

存储

https://github.com/weloe/token-go/blob/f58ba4d93f0f012972bf6a35b9127229b5c328fe/enforcer.go#L192

在存储的时候,需要拼接key防止与其他的key重复

	// reset session
	err = e.SetSession(id, session, loginModel.Timeout)
	if err != nil {
		return "", err
	}

	// set token-id
	err = e.adapter.SetStr(e.spliceTokenKey(tokenValue), id, loginModel.Timeout)
	if err != nil {
		return "", err
	}

返回toke

首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇解决xorm逆向工程问题 下一篇夜莺初探四·mtail插件采集日志指..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目