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

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

复制上面javascript代码到浏览器console中执行就可以解析出用户信息了! 当然你要可以使用在线工具来解析jwt token的payload荷载
JWT在线解析工具

4. go语言Gin框架实现JWT用户认证

接下来我将使用最受欢迎的gin-gonic/gin 和 dgrijalva/jwt-go

这两个package来演示怎么使用JWT身份认证.

4.1 登录接口

4.1.1 登录接口路由(login-route)

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


  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) //管理后台登陆

internal.LoginCommenterinternal.LoginAdmin 这两个方法是一样的,
只需要关注其中一个就可以了,我们就关注internal.LoginCommenter

4.1.2 登录login handler

编写登录的handler

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


func LoginCommenter(c *gin.Context) {
  var mdl model.User
  err := c.ShouldBind(&mdl)
  if handleError(c, err) {
    return
  }
  //获取ip
  ip := c.ClientIP()
  //roleId 8 是评论系统的用户
  data, err := mdl.Login(ip, 8)
  if handleError(c, err) {
    return
  }
  jsonData(c, data)
}

其中最关键的是mdl.Login(ip, 8)这个函数
https://github.com/libragen/felix/blob/master/model/m_users.go

1.数据库查询用户 2.校验用户role_id 3.比对密码 4.防止密码泄露(清空struct的属性) 5.生成JWT-string

//Login
func (m *User) Login(ip string, roleId uint) (string, error) {
  m.Id = 0
  if m.Password == "" {
    return "", errors.New("password is required")
  }
  inputPassword := m.Password
  //获取登录的用户
  err := db.Where("username = ? or email = ?", m.Username, m.Username).First(&m).Error
  if err != nil {
    return "", err
  }
  //校验用户角色
  if (m.RoleId & roleId) != roleId {
    return "", fmt.Errorf("not role of %d", roleId)
  }
  //验证密码
  //password is set to bcrypt check
  if err := bcrypt.CompareHashAndPassword([]byte(m.HashedPassword), []byte(inputPassword)); err != nil {
    return "", err
  }
  //防止密码泄露
  m.Password = ""
  //生成jwt-string
  return jwtGenerateToken(m, time.Hour*24*365)
}