Gin 系列讲座: Saas系统, Gin+Jwt+casbin RestFul Api 后端一战到底 5: jwt token login详解

1,422 阅读2分钟

JWT token 10秒入门

什么是JWT token? 全称 JSON WEB TOKEN , 用我们能听懂的话来描述,就是 全栈开发中 完全前后端分离后 用户验证需要到一个加密字符串. 一般是存在于数据库中到用户, 根据用户名,密码登陆后.如果正确,就会返回一个这样token字符串.

登陆成功后得到到token 有什么用?

拿到这个toke. 就意味者你又一定的权限可有访问 有权限到资源了, 举个例子. 比如用户想从前端访问 写文章 /article/write 到这么一个资源权限(只有toke正确才能访问), 其实简单理解就是这么个意思.

jwt 内容

现在回头来看token的定义. 一个JWT实际上就是一个字符串,它由三部分组成,头部、载荷与签名依顺序用点号(".")链接而成:1.header,2.payload,3.signature。 具体功能我们不描述了,大家查查资料. 现在来看一下toke什么样

eyJ0eXAiOisV1QiLCJhbGciOiJIUzI1NiJ9

好了,那么知道这东西那么有用,我们go 后端gin框架怎么用呢? 好问题

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) //管理后台登陆
    ```
    
    上次写的CROS大家不明白到可有看一下. 关键来说是http heade中加上"Authorization" 跨域允许
    
    #### 用户登陆处理生成token
    ```
    //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)
}

用户拿到token 可有存在cookie, 或者后端到session中 另外 可有通过gin到中间件缓存在context中

func UserAuthMiddleware(a auth.Auther, skipper ...SkipperFunc) gin.HandlerFunc {
	return func(c *gin.Context) {
		var userID string
		if t := ginplus.GetToken(c); t != "" {
			id, err := a.ParseUserID(t)
			if err != nil {
				if err == auth.ErrInvalidToken {
					ginplus.ResError(c, errors.ErrNoPerm)
					return
				}
				ginplus.ResError(c, errors.WithStack(err))
				return
			}
			userID = id
		}

		

客户端在访问 /article/writer 在http header 中加上这个jwt token 这时候就可有正确访问了.

后面会在详细给出jwt实战,完整工程到例子.

总结

jwt 相对与前后端分离到项目还是比较方便到.