golang实现SSO(单点登录)

lannisiter · · 2680 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

单点登录是一个我们平常经常能见到的功能,就是一个账号同一时间只能在一台设备上登录,后登录的设备会挤掉先登录的设备,比如我们的手机qq,如果在自己手机上登录了自己的qq账号,然后另一部手机上接着登录自己的qq,那么自己手机上的qq就会下线。

实现单点登录

实现单点登录的思路很简单,就是一个账号对应的token同一时间只有一个生效,也就是说每次用户登录除了生成一个token保存起来,还要删除掉之前的token。

  1. 用户登录,服务器生成token保存至redis(设置有效时间),并将token返回给前端,用户之后的每次请求需要携带token。
  2. 在拦截器中校验请求头中的token,判断token是否有效,每一次有效的请求都刷新token的有效时间。
  3. 同一个账号再次被登录时,删除之前的token,并生成新的token重复1操作。

步骤看起来都很简单,但有一个问题需要注意,每一次校验token是需要去redis中查询的,也就是说设置的key应该为token,value为userId(或者其它唯一标识),那么这个时候如何在登录时做到删除当前的token呢?如果只是有一个token-id的对应关系好像确实没办法获取到该账号当前token,所以还需要一个id-token的对应关系,可以直接通过id拿到token。

这里附上我实现token操作部分的代码,拦截器部分可以有很多种实现方式,我是用的echo框架的中间件来实现,如果需要的话评论区说一声我贴上来。

CreateToken(key string, expiration time.Duration) string:创建token,我在创建token的时候就会去判断是否存在旧的token然后删除。

ValidToken(token string) (id int):验证token是否有效,0为失效。

DelToken(token string):删除redis中的token信息。

/**
 * @Author lanni
 * @Description 创建token
 * @Date 2020/6/18 15:50
 * @Param key:登陆凭证(id),expiration:过期时间
 * @return token:令牌
 **/
func CreateToken(key string, expiration time.Duration) string {
   //生成token,这里生成token可以自己选择一个算法来生成,只要是长度足够的随机字符串就ok
   token := jwt.GenerateToken(key)
   //redis记录该账号登录状态
   client := redis.Open()
   defer client.Close()
   client.Set(token, key, expiration)
   //获取原token
   oldToken := client.Get(key)
   //如果原token不为空则删除
   if oldToken != "" {
      client.Del(oldToken)
   }
   //保存或更新该账号的当前登录token,用于单点登录
   client.Set(key, token, expiration)
   return token
}

/**
 * @Author lanni
 * @Description 验证token是否过期
 * @Date 2020/6/18 16:03
 * @Param
 * @return 返回token对应的id,查询为空时返回0
 **/
func ValidToken(token string) (id int) {
   //查询
   client = redis.Open()
   defer client.Close()
   id, err := strconv.Atoi(client.Get(token))
   if id != 0 && err == nil {
      return
   }
   return 0
}

/**
 * @Author lanni
 * @Description 删除sso中的token信息
 * @Date 2020/7/9 15:32
 * @Param
 * @return
 **/
func DelToken(token string) {
   client := redis.Open()
   defer client.Close()
   //获取原token对应的id
   id := client.Get(token)
   //token时限设置为1s
   client.Set(token, id, time.Second)
   client.Set(id, token, time.Second)
}

有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:lannisiter

查看原文:golang实现SSO(单点登录)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:701969077

2680 次点击  
加入收藏 微博
上一篇:gnet框架
下一篇:我一定坚持
2 回复  |  直到 2022-01-01 11:52:41
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传