fly-用户登陆&鉴权

204 阅读5分钟

inbox

getinfo 接口:

整体登陆-鉴权流程

  1. /login接口,post,输入:用户名-密码-验证码-uuid,handler为LoginHandler

  2. LoginHandler内部:

    1. 然后用户验证auth:jwtauth这个中间件实例化时传入的回调,Authenticator函数处理(用户名-密码-验证码-uuid)

      1. 从c中解析数据,bind到结构体实例中,通过后:
      2. 三方验证码库,根据uuid和code,进行校验,通过后:
      3. 根据username 用户名,查询用户名,获得user实例,查表
      4. 再根据user实例中的roleId,获得role的示例,查表
      5. 把user实例,role实例,组成一个map,返回该map
      6. 总结:验证用户名-密码-验证码,通过后,查表取到该用户对应的user实例、role实例,组成map,然后返回,这里map假设变量为data 其结构: {"user": user实例, "role" : role实例}
    2. 实例化一个空的token实例,以及一个空的claims容器:类型map[string]interface (借助jwt三方库)

    3. payloadFunc,负载数据挂入(也是jwtauth中间件实例化时传入的回调)

      1. 接收一个interface{}空接口类型,即可接收任意类型,(实际业务代码传入的auth函数中处理得到的data数据,是个map,
      2. 先对data进行类型断言:data.(map[string]interface{})
      3. 根据user这个key,取出user实例,类型断言
      4. 根据role这个key,取出role实例,类型断言
      5. 从user、role实例取出一些字段,组成一个map数据并返回,类型map[string]interface{},具体内容如下:
      {
      "identity": user类型实例模型的UserId int类型
      "roleid" : role类型实例的 RoleId int类型
      "rolekey": role类型实例的 RoleKey string 角色代码、描述符,比如admin、devlop
      "nice": user类型实例的 UserName 字段 string
      "nickName": user类型实例的 Nickname 字段 string
      "datascope": role类型实例的 DataScope字段 string
      "rolename": role类型实例的 RoleName 字段 string
      }
      
    4. payloadFunc()调用得到返回的map,然后进行遍历,key、value分别填充到上文空的claims这个map中

    5. claims,再添加2组键值对,“exp”和“orig_iat” ,分别表示下一次过期的时间点,和这次token的生成时间

    6. 借助jwt库,把填充了实际数据claim的token,转换为token字符串此时token字符串,就包含了上述的7个字段信息

    7. 如果还配置了,setCookie选项,则把token字符串,组成cookie,也发到cookie里一份

    8. 响应客户端,主要内容就是token字符串

鉴权中间件(对所有需要鉴权的接口生效)

  1. 先从c对象中取出token字符串(这里假设只考虑token在http的头部传入的情况)
  2. 得到的token字符串,再有jwt三方库解析为*jwt.token对象
  3. 实例化一个空的map容器,map[string]interface{}类型
  4. 再从token对象中取出Claims数据(map),进行遍历,添加到claims这个空的map容器中, 此时claims的数据应该如下:
{
     "identity": user类型实例模型的UserId int类型
     "roleid" : role类型实例的 RoleId int类型
     "rolekey": role类型实例的 RoleKey string 角色代码、描述符,比如admin、devlop
     "nice": user类型实例的 UserName 字段 string
     "nickName": user类型实例的 Nickname 字段 string
     "datascope": role类型实例的 DataScope字段 string
     "rolename": role类型实例的 RoleName 字段 string
     "exp": 过期时间点
     "orig_iat": token生成时间点
     }
  1. 判断claims中的exp字段,是否为空、格式是否正确、是否过期,全部验证通过后!

  2. 把claims数据,挂载到c对象上,字段为:"JWT_PAYLOAD",值是map,(之后的handler,只需要c.Get("JWT_PAYLOAD") 即可访问到claims这个map,进而得到它的9个字段信息,”JWT_PAYLOAD“ 的标识符为 JwtPayloadKey

  3. 调用函数IdentityHandler()也是jwtauth中间件实例化时传入的回调,

    1. 从c中抽取claims信息,就是通过c.Get(JwtPayloadKey)获得的,得到全部9个字段的map
    2. 然后再从完整的map中,抽取身份鉴权相关的6个字段,组成一个新的map,如下:
    	return map[string]interface{}{
                     "IdentityKey": claims["identity"], # 对应原:user实例的UserId int 类型
                     "UserName":    claims["nice"], 
                     "RoleKey":     claims["rolekey"], 
                     "UserId":      claims["identity"], # 对应原:user实例和UserId int类型
                     "RoleIds":     claims["roleid"], 
                     "DataScope":   claims["datascope"],
             }
    
    1. 返回所组成的新的map,
  4. 然后把IdentityHandler返回的新的map映射,也挂载到c实例上 c.Set(IdentityKey, 新map)IdentityKey是字符串”identity“的标识符 6.注意:此时:c实例上有个key,”JWT_PAYLOAD“ 对应的值为 完整的claim信息,如下图数据1; 第二个key ”identity“ 它对应的值为 下图数据2

# 数据1map[string]interface{}{
                     "identity": user类型实例模型的UserId int类型
                     "roleid" : role类型实例的 RoleId int类型
                     "rolekey": role类型实例的 RoleKey string 角色代码、描述符,比如admin、devlop
                     "nice": user类型实例的 UserName 字段 string
                     "nickName": user类型实例的 Nickname 字段 string
                     "datascope": role类型实例的 DataScope字段 string
                     "rolename": role类型实例的 RoleName 字段 string
                     "exp": 过期时间点
                     "orig_iat": token生成时间点
                     }

# 数据2map[string]interface{}{
                     "IdentityKey": claims["identity"], # 对应原:user实例的UserId int 类型
                     "UserName":    claims["nice"], 
                     "RoleKey":     claims["rolekey"], 
                     "UserId":      claims["identity"], # 对应原:user实例和UserId int类型
                     "RoleIds":     claims["roleid"], 
                     "DataScope":   claims["datascope"],
             }

9.最后一步鉴权:authorizator ,也是jwtauth 中间件实例化时,传入的回调,这里懵了!——传入的回调如下:但是代码里,data的实参为上一步的identity 的返回的新map,样式是(数据2),哪里来的user和role的 key?



// 自定义鉴权的hook,但是哪里体现鉴权了QA
func Authorizator(data interface{}, c *gin.Context) bool {

 if v, ok := data.(map[string]interface{}); ok {
 	u, _ := v["user"].(models.SysUser)
 	r, _ := v["role"].(models.SysRole)
 	c.Set("role", r.RoleName)
 	c.Set("roleIds", r.RoleId)
 	c.Set("userId", u.UserId)
 	c.Set("userName", u.UserName)
 	c.Set("nickName", u.NickName)
 	c.Set("dataScope", r.DataScope)

 	return true
 }
 return false
}