gtoken替换jwt实现sso登录

简介: 今天和大家分享一下使用gtoken替换jwt实现sso登录的经验,为了让大家更好的理解会带大家读一下重点的源码。

今天和大家分享一下使用gtoken替换jwt实现sso登录的经验,为了让大家更好的理解会带大家读一下重点的源码。
jwt的问题
首先说明一个jwt存在的问题,也就是要替换jwt的原因:

jwt无法在服务端主动退出的问题
jwt无法作废已颁布的令牌,只能等到令牌过期问题
jwt携带大量用户扩展信息导致降低传输效率问题

jwt的请求流程图

gtoken的优势
gtoken的请求流程和jwt的基本一致。
gtoken的优势就是能帮助我们解决jwt的问题,另外还提供好用的特性,比如:

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

注意问题

支持服务端缓存自动续期功能,不需要通过refresh_token刷新token,简化了客户端的操作

版本问题千万注意:在gtoken v1.5.0全面适配GoFrame v2.0.0 ; GoFrame v1.X.X 请使用GfToken v1.4.X相关版本

TIPS:下面我的演示demo和源码阅读都是基于v1.4.x版本的。
演示demo
下面的演示demo可以复制到本地main.go文件中执行,更新依赖的时候千万注意版本。
重点说一下踩的坑:
Login方法会要求我们返回两个值:
第一个值对应userKey,后续我们可以根据userKey获得token
第二个值对应data,是interface{}类型,我们可以在这里定义例如userid、username等数据。
先有这个概念即可,后面会带大家读源码。
package main

import (
"github.com/goflyfox/gtoken/gtoken"
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/net/ghttp"
"github.com/gogf/gf/os/glog"
)

var TestServerName string

//var TestServerName string = "gtoken"

func main() {
glog.Info("########service start...")

g.Cfg().SetPath("example/sample")
s := g.Server(TestServerName)
initRouter(s)

glog.Info("########service finish.")
s.Run()
}

var gfToken *gtoken.GfToken

/*
统一路由注册
*/
func initRouter(s *ghttp.Server) {
// 不认证接口
s.Group("/", func(group *ghttp.RouterGroup) {

  group.Middleware(CORS)

  // 调试路由
  group.ALL("/hello", func(r *ghttp.Request) {
     r.Response.WriteJson(gtoken.Succ("hello"))
  })

})

// 认证接口
loginFunc := Login
// 启动gtoken
gfToken := &gtoken.GfToken{

  ServerName:       TestServerName,
  LoginPath:        "/login",
  LoginBeforeFunc:  loginFunc,
  LogoutPath:       "/user/logout",
  AuthExcludePaths: g.SliceStr{"/user/info", "/system/user/info"}, // 不拦截路径 /user/info,/system/user/info,/system/user,
  MultiLogin:       g.Config().GetBool("gToken.MultiLogin"),

}
s.Group("/", func(group *ghttp.RouterGroup) {

  group.Middleware(CORS)
  gfToken.Middleware(group)

  group.ALL("/system/user", func(r *ghttp.Request) {
     r.Response.WriteJson(gtoken.Succ("system user"))
  })
  group.ALL("/user/data", func(r *ghttp.Request) {
     r.Response.WriteJson(gfToken.GetTokenData(r))
  })
  group.ALL("/user/info", func(r *ghttp.Request) {
     r.Response.WriteJson(gtoken.Succ("user info"))
  })
  group.ALL("/system/user/info", func(r *ghttp.Request) {
     r.Response.WriteJson(gtoken.Succ("system user info"))
  })

})

// 启动gtoken
gfAdminToken := &gtoken.GfToken{

  ServerName: TestServerName,
  //Timeout:         10 * 1000,
  LoginPath:        "/login",
  LoginBeforeFunc:  loginFunc,
  LogoutPath:       "/user/logout",
  AuthExcludePaths: g.SliceStr{"/admin/user/info", "/admin/system/user/info"}, // 不拦截路径 /user/info,/system/user/info,/system/user,
  MultiLogin:       g.Config().GetBool("gToken.MultiLogin"),

}
s.Group("/admin", func(group *ghttp.RouterGroup) {

  group.Middleware(CORS)
  gfAdminToken.Middleware(group)

  group.ALL("/system/user", func(r *ghttp.Request) {
     r.Response.WriteJson(gtoken.Succ("system user"))
  })
  group.ALL("/user/info", func(r *ghttp.Request) {
     r.Response.WriteJson(gtoken.Succ("user info"))
  })
  group.ALL("/system/user/info", func(r *ghttp.Request) {
     r.Response.WriteJson(gtoken.Succ("system user info"))
  })

})
}

func Login(r *ghttp.Request) (string, interface{}) {
username := r.GetString("username")
passwd := r.GetString("passwd")

if username == "" || passwd == "" {

  r.Response.WriteJson(gtoken.Fail("账号或密码错误."))
  r.ExitAll()

}

return username, "1"
/**
返回的第一个参数对应:userKey
返回的第二个参数对应:data
{

   "code": 0,
   "msg": "success",
   "data": {
       "createTime": 1652838582190,
       "data": "1",
       "refreshTime": 1653270582190,
       "userKey": "王中阳",
       "uuid": "ac75676efeb906f9959cf35f779a1d38"
   }

}
*/
}

// 跨域
func CORS(r *ghttp.Request) {
r.Response.CORSDefault()
r.Middleware.Next()
}
复制代码
启动项目:

访问不认证接口:返回成功

未登录时访问认证接口:返回错误

请求登录接口:返回token

携带token再次访问认证接口:返回成功

以上就跑通了主体流程,就是这么简单。

相关文章
|
3月前
|
SQL Java 测试技术
在Spring boot中 使用JWT和过滤器实现登录认证
在Spring boot中 使用JWT和过滤器实现登录认证
211 0
|
6月前
|
安全 Java 应用服务中间件
Shiro + JWT 进行登录验证
Shiro + JWT 进行登录验证
55 2
|
23天前
|
JavaScript
Node.js单点登录SSO详解:Session、JWT、CORS让登录更简单(二)
Node.js单点登录SSO详解:Session、JWT、CORS让登录更简单(一)
25 0
|
23天前
|
存储 JSON JavaScript
Node.js单点登录SSO详解:Session、JWT、CORS让登录更简单(一)
Node.js单点登录SSO详解:Session、JWT、CORS让登录更简单(一)
72 0
|
3月前
【Azure APIM】在APIM中实现JWT验证不通过时跳转到Azure登录页面
【Azure APIM】在APIM中实现JWT验证不通过时跳转到Azure登录页面
|
4月前
|
存储 JavaScript 前端开发
文本,三步走构思,富文本点击提交能够存储到数据库当中(下),最快的方法,还是会看资料,因此会整合资料最好,直接看资料最快,因为是JWT的资料,我们要设置好登录的内容,看登录的地方怎样写的
文本,三步走构思,富文本点击提交能够存储到数据库当中(下),最快的方法,还是会看资料,因此会整合资料最好,直接看资料最快,因为是JWT的资料,我们要设置好登录的内容,看登录的地方怎样写的
|
4月前
|
安全 NoSQL Java
JWT和Security 登录权限判断和token访问和让token失效
JWT和Security 登录权限判断和token访问和让token失效
|
5月前
|
JSON 算法 Go
go语言后端开发学习(一)——JWT的介绍以及基于JWT实现登录验证
go语言后端开发学习(一)——JWT的介绍以及基于JWT实现登录验证
|
6月前
|
安全 关系型数据库 MySQL
node实战——后端koa结合jwt连接mysql实现权限登录(node后端就业储备知识)
node实战——后端koa结合jwt连接mysql实现权限登录(node后端就业储备知识)
105 3
|
6月前
|
前端开发 NoSQL 数据库
切图仔做全栈:React&Nest.js社区平台(一)——基础架构与邮箱注册、JWT登录实现
切图仔做全栈:React&Nest.js社区平台(一)——基础架构与邮箱注册、JWT登录实现

热门文章

最新文章