详解Go-JWT-RESTful身份认证教程

2020-01-28 14:15:38于丽

4.使用了jwt-middle之后的handle从gin.Context中获取用户信息

https://github.com/libragen/felix/blob/master/ssh2ws/internal/mw_jwt.go


package internal

import (
  "net/http"
  "strings"

  "github.com/libragen/felix/model"
  "github.com/gin-gonic/gin"
)

const contextKeyUserObj = "authedUserObj"
const bearerLength = len("Bearer ")

func ctxTokenToUser(c *gin.Context, roleId uint) {
  token, ok := c.GetQuery("_t")
  if !ok {
    hToken := c.GetHeader("Authorization")
    if len(hToken) < bearerLength {
      c.AbortWithStatusJSON(http.StatusPreconditionFailed, gin.H{"msg": "header Authorization has not Bearer token"})
      return
    }
    token = strings.TrimSpace(hToken[bearerLength:])
  }
  usr, err := model.JwtParseUser(token)
  if err != nil {
    c.AbortWithStatusJSON(http.StatusPreconditionFailed, gin.H{"msg": err.Error()})
    return
  }
  if (usr.RoleId & roleId) != roleId {
    c.AbortWithStatusJSON(http.StatusPreconditionFailed, gin.H{"msg": "roleId 没有权限"})
    return
  }

  //store the user Model in the context
  c.Set(contextKeyUserObj, *usr)
  c.Next()
  // after request
}

func MwUserAdmin(c *gin.Context) {
  ctxTokenToUser(c, 2)
}

func MwUserComment(c *gin.Context) {
  ctxTokenToUser(c, 8)
}

使用了jwt-middle之后的handle从gin.Context中获取用户信息,
https://github.com/libragen/felix/blob/master/ssh2ws/internal/helper.go


func mWuserId(c *gin.Context) (uint, error) {
  v,exist := c.Get(contextKeyUserObj)
  if !exist {
    return 0,errors.New(contextKeyUserObj + " not exist")
  }
  user, ok := v.(model.User)
  if ok {
    return user.Id, nil
  }
  return 0,errors.New("can't convert to user struct")
}

4.2 使用JWT中间件

一下代码有两个JWT中间件的用法

internal.MwUserAdmin 管理后台用户中间件 internal.MwUserCommenter 评论用户中间件

https://github.com/libragen/felix/blob/master/ssh2ws/ssh2ws.go


package ssh2ws

import (
  "time"

  "github.com/libragen/felix/felixbin"
  "github.com/libragen/felix/model"
  "github.com/libragen/felix/ssh2ws/internal"
  "github.com/libragen/felix/wslog"
  "github.com/gin-contrib/cors"
  "github.com/gin-gonic/gin"
)

func RunSsh2ws(bindAddress, user, password, secret string, expire time.Duration, verbose bool) error {
  err := model.CreateGodUser(user, password)
  if err != nil {
    return err
  }
  //config jwt variables
  model.AppSecret = secret
  model.ExpireTime = expire
  model.AppIss = "felix.mojotv.cn"
  if !verbose {
    gin.SetMode(gin.ReleaseMode)
  }
  r := gin.New()
  r.MaxMultipartMemory = 32 << 20
  //sever static file in http's root path
  binStaticMiddleware, err := felixbin.NewGinStaticBinMiddleware("/")
  if err != nil {
    return err
  }

  mwCORS := cors.New(cors.Config{
    AllowOrigins:   []string{"*"},
    AllowMethods:   []string{"PUT", "PATCH", "POST", "GET", "DELETE"},
    AllowHeaders:   []string{"Origin", "Authorization", "Content-Type"},
    ExposeHeaders:  []string{"Content-Type"},
    AllowCredentials: true,
    AllowOriginFunc: func(origin string) bool {
      return true
    },
    MaxAge: 2400 * time.Hour,
  })
  r.Use(binStaticMiddleware, mwCORS)


  {
    r.POST("comment-login", internal.LoginCommenter)    //评论用户登陆
    r.POST("comment-register", internal.RegisterCommenter) //评论用户注册
  }

  api := r.Group("api")
  api.POST("admin-login", internal.LoginAdmin) //管理后台登陆
  api.GET("meta", internal.Meta)

  //terminal log
  hub := wslog.NewHub()
  go hub.Run()

  {
    //websocket
    r.GET("ws/hook", internal.MwUserAdmin, internal.Wslog(hub))
    r.GET("ws/ssh/:id", internal.MwUserAdmin, internal.WsSsh)
  }
  //给外部调用
  {
    api.POST("wslog/hook-api", internal.JwtMiddlewareWslog, internal.WsLogHookApi(hub))
    api.GET("wslog/hook", internal.MwUserAdmin, internal.WslogHookAll)
    api.POST("wslog/hook", internal.MwUserAdmin, internal.WslogHookCreate)
    api.PATCH("wslog/hook", internal.MwUserAdmin, internal.WslogHookUpdate)
    api.DELETE("wslog/hook/:id", internal.MwUserAdmin, internal.WslogHookDelete)

    api.GET("wslog/msg", internal.MwUserAdmin, internal.WslogMsgAll)
    api.POST("wslog/msg-rm", internal.MwUserAdmin, internal.WslogMsgDelete)
  }

  //评论
  {
    api.GET("comment", internal.CommentAll)
    api.GET("comment/:id/:action", internal.MwUserComment, internal.CommentAction)
    api.POST("comment", internal.MwUserComment, internal.CommentCreate)
    api.DELETE("comment/:id", internal.MwUserAdmin, internal.CommentDelete)
  }
  {
    api.GET("hacknews",internal.MwUserAdmin, internal.HackNewAll)
    api.PATCH("hacknews", internal.HackNewUpdate)
    api.POST("hacknews-rm", internal.HackNewRm)
  }

  authG := api.Use(internal.MwUserAdmin)
  {

    //create wslog hook

    authG.GET("ssh", internal.SshAll)
    authG.POST("ssh", internal.SshCreate)
    authG.GET("ssh/:id", internal.SshOne)
    authG.PATCH("ssh", internal.SshUpdate)
    authG.DELETE("ssh/:id", internal.SshDelete)

    authG.GET("sftp/:id", internal.SftpLs)
    authG.GET("sftp/:id/dl", internal.SftpDl)
    authG.GET("sftp/:id/cat", internal.SftpCat)
    authG.GET("sftp/:id/rm", internal.SftpRm)
    authG.GET("sftp/:id/rename", internal.SftpRename)
    authG.GET("sftp/:id/mkdir", internal.SftpMkdir)
    authG.POST("sftp/:id/up", internal.SftpUp)

    authG.POST("ginbro/gen", internal.GinbroGen)
    authG.POST("ginbro/db", internal.GinbroDb)
    authG.GET("ginbro/dl", internal.GinbroDownload)

    authG.GET("ssh-log", internal.SshLogAll)
    authG.DELETE("ssh-log/:id", internal.SshLogDelete)
    authG.PATCH("ssh-log", internal.SshLogUpdate)

    authG.GET("user", internal.UserAll)
    authG.POST("user", internal.RegisterCommenter)
    //api.GET("user/:id", internal.SshAll)
    authG.DELETE("user/:id", internal.UserDelete)
    authG.PATCH("user", internal.UserUpdate)

  }

  if err := r.Run(bindAddress); err != nil {
    return err
  }
  return nil
}