美文网首页
golang实现单设备登录

golang实现单设备登录

作者: lannisiter | 来源:发表于2020-11-01 11:09 被阅读0次

    单设备登录是一个我们平常经常能见到的功能,就是一个账号同一时间只能在一台设备上登录,后登录的设备会挤掉先登录的设备,比如我们的手机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)
    }
    

    相关文章

      网友评论

          本文标题:golang实现单设备登录

          本文链接:https://www.haomeiwen.com/subject/oisyvktx.html