介绍

基于GoFrame框架的token插件,通过服务端验证方式实现token认证;已完全可以支撑线上token认证,通过Redis支持集群模式;使用简单,大家可以放心使用;


全面适配GoFrame v2.0.0  ; GoFrame v1.X.X 请使用gtoken v1.4.X相关版本。

gtoken优势

  1. gtoken支撑单点应用使用内存存储,也支持集群使用redis存储;完全适用于企业生产级使用;
  2. 有效的避免了jwt服务端无法退出问题;
  3. 解决jwt无法作废已颁布的令牌,只能等到令牌过期问题;
  4. 通过用户扩展信息存储在服务端,有效规避了jwt携带大量用户扩展信息导致降低传输效率问题;
  5. 有效避免jwt需要客户端实现续签功能,增加客户端复杂度;支持服务端自动续期,客户端不需要关心续签逻辑;

特性说明

  1. 支持token认证,不强依赖于session和cookie,适用jwt和session认证所有场景;
  2. 支持单机gcache和集群gredis模式;
# 缓存模式 1 gcache 2 gredis 3 fileCache
CacheMode = 2

支持服务端缓存自动续期功能
// 注:通过MaxRefresh,默认当用户第五天访问时,自动续期
// 超时时间 默认10天
Timeout int
// 缓存刷新时间 默认为超时时间的一半
MaxRefresh int
  1. 支持分组拦截、全局拦截、深度路径拦截,便于根据个人需求定制拦截器;建议使用分组拦截方式;
  2. 框架使用简单,只需要设置登录验证方法以及登录、登出路径即可;
  3. gtoken v1.4.0版本开始支持分组中间件方式实现,但依然兼容全局和深度中间件实现方式;

感谢

gf框架 https://github.com/gogf/gf

  • No labels

19 Comments

  1. gfile.TempDir(CacheModeFileDat)中提示TempDir找不到,gtoken@v1.5.3,还没是适配gf@v2?

    1. FLY的狐狸 彪哥,gfile.TempDir改为了gfile.Temp了,gtoken更新一发?另外,请不要喷我,这已经是v2了。

    2. GoFrame集成gtoken视频详解,包括v2和v1两个版本: https://www.bilibili.com/video/BV1v841157Bh/

  2. group.Bind(
    controller.User,
    )

    这种方式 gToken 该怎么呢,有没有例子? 

    1. 我重新描述一下,用gf init 创建的项目结构。

      api/v1/user 定义访问路径,请求参数等等。

      controller.User 处理逻辑,那我怎么样创建 gToken 呢? 

  3. FLY的狐狸 参考了您的gtoken源码,有一个疑问,怎么结合 MiddlewareAuth, MiddlewareErrorHandler:路由管理-中间件/拦截器 文中有提到,MiddlewareAuth校验失败,可以直接退出,那么是否可以先不退出,继续让MiddlewareErrorHandler处理完之后,返回统一的结果处理之后在退出呢?

    在gtoken中也有体现:

    if m.AuthAfterFunc == nil {
            m.AuthAfterFunc = func(r *ghttp.Request, respData Resp) {
                if respData.Success() {
                    r.Middleware.Next()
                } else {
                    var params map[string]interface{}
                    if r.Method == http.MethodGet {
                        params = r.GetMap()
                    } else if r.Method == http.MethodPost {
                        params = r.GetMap()
                    } else {
                        r.Response.Writeln(MsgErrReqMethod)
                        return
                    }
    
                    no := gconv.String(gtime.TimestampMilli())
    
                    g.Log().Warning(r.Context(), fmt.Sprintf("[AUTH_%s][url:%s][params:%s][data:%s]",
                        no, r.URL.Path, params, respData.Json()))
                    respData.Msg = m.AuthFailMsg
                    err := r.Response.WriteJson(respData)
                    if err != nil {
                        g.Log().Error(r.Context(), err)
                    }
                    r.ExitAll()
                }
            }
        }

    当执行 m.AuthAfterFunc(r, tokenResp) 时,该方法要是校验失败,即respData.Success()为false,那么最后会修改完成response之后,执行exitAll退出。


    是否可以继续执行后续的Middleware 呢?

  4. 请问想要在登录返回参数中加入自定义参数应该如何实现呢

    1. 修改自己的login方法,比如这个是gtoken的示例代码:

      func Login(r *ghttp.Request) (string, interface{}) {
      	username := r.Get("username").String()
      	passwd := r.Get("passwd").String()
      
      	if username == "" || passwd == "" {
      		r.Response.WriteJson(gtoken.Fail("账号或密码错误."))  // 你可以在这里修改response的返回值
      		r.ExitAll()
      	}
      	// 唯一标识,扩展参数user data
      	return username, "1"
      }
      
      
      1. 好的,谢谢,有帮到我,我现在是使用loginAfterFunc里修改response自定义返回参数。

  5. 请问启动gtoken的路由组是不是组内就不支持标准路由方式了?

  6. 如果能介绍一下设计思想就好了。

  7. 那这个token怎么生成呢?

    1. 认真看源码呀, EncryptToken


      func (m *GfToken) EncryptToken(ctx context.Context, userKey string, uuid string) Resp {
      	if userKey == "" {
      		return Fail(MsgErrUserKeyEmpty)
      	}
      
      	if uuid == "" {
      		// 重新生成uuid
      		newUuid, err := gmd5.Encrypt(grand.Letters(10))
      		if err != nil {
      			g.Log().Error(ctx, msgLog(MsgErrAuthUuid), err)
      			return Error(MsgErrAuthUuid)
      		}
      		uuid = newUuid
      	}
      
      	tokenStr := userKey + m.TokenDelimiter + uuid
      
      	token, err := gaes.Encrypt([]byte(tokenStr), m.EncryptKey)
      	if err != nil {
      		g.Log().Error(ctx, msgLog(MsgErrTokenEncrypt), tokenStr, err)
      		return Error(MsgErrTokenEncrypt)
      	}
      
      	return Succ(g.Map{
      		KeyUserKey: userKey,
      		KeyUuid:    uuid,
      		KeyToken:   gbase64.EncodeToString(token),
      	})
      }
  8. 通过gtoken拦截的登录登出接口好像没办法生成openapi文档了,这块有什么办法吗?

    1. 同问,有知道怎么生成么?

  9. 如果使用默认缓存在 gCache 里,每次修改完业务代码重启服务后,token就会失效,如何在开发时关闭 gToken,而在上线调试时自动打开?我想的是配置环境变量,但不知如何下手,请大佬帮忙,谢谢!

  10. 有点不太懂得是:如果被缓存或者存储了,这样与session的区别是什么?