在jwt-go 中我记录了手动封装一个认证中间件,然后今天在看go-admin 后台管理系统源码的时候发现作者用到了一个第三方库gin-jwt 实现了同样的功能,今天就一起来看一下吧!
gin-jwt能做什么? 
源码分析 整个框架就一个auth_jwt.go 文件,共747行代码。我们从头往下看:
先定义了一个返回值为map类型的接口type MapClaims map[string]interface{}
接着就是一个结构体GinJWTMiddleware,还记得我们在使用jwt-go的时候,也会定义一个结构体,里面存放了关于生成token的一些信息,包括:token发放时间、是谁发放的token、主题等,这里也一样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 type  GinJWTMiddleware struct {	// Realm name to display to the user. Required. 	Realm string 	// 算法类型: HS256, HS384, HS512默认是 HS256. 	SigningAlgorithm string 	// 加密密钥. 	Key []byte 	// 刷新Token有效期.默认一个小时 	MaxRefresh time.Duration 	// 认证回调函数 	Authenticator func(c *gin.Context) (interface{}, error) 	// 通过认证后的处理函数 	Authorizator func(data interface{}, c *gin.Context) bool 	// 认证失败的回调函数 	Unauthorized func(*gin.Context, int, string) 	//登录响应函数 	LoginResponse func(*gin.Context, int, string, time.Time) 	// 超时响应函数 	LogoutResponse func(*gin.Context, int) 	// 刷新响应函数 	RefreshResponse func(*gin.Context, int, string, time.Time) } 
函数(只列了几个目前见到的)
登录返回token
1 2 3 4 5 6 // LoginHandler can be used by clients to get a jwt token. // Payload needs to be json in  the form of {"username" : "USERNAME" , "password" : "PASSWORD" }. // Reply will be of the form {"token" : "TOKEN" }. func (mw *GinJWTMiddleware) LoginHandler(c *gin.Context) { 	... } 
刷新token
1 2 3 4 5 6 7 8 9 10 11 12 // RefreshHandler can be used to refresh a token. The token still needs to be valid on refresh. // Shall be put under an endpoint that is using the GinJWTMiddleware. // Reply will be of the form {"token" : "TOKEN" }. func (mw *GinJWTMiddleware) RefreshHandler(c *gin.Context) { 	tokenString, expire, err := mw.RefreshToken(c) 	if  err != nil { 		mw.unauthorized(c, http.StatusUnauthorized, mw.HTTPStatusMessageFunc(err, c)) 		return  	} 	mw.RefreshResponse(c, http.StatusOK, tokenString, expire) } 
验证API时需要用到,例如检测权限
1 2 3 4 5 6 // MiddlewareFunc makes GinJWTMiddleware implement the Middleware interface. func (mw *GinJWTMiddleware) MiddlewareFunc() gin.HandlerFunc { 	return  func(c *gin.Context) { 		mw.middlewareImpl(c) 	} } 
示例 测试官方demo 源码地址:https://github.com/samtake/gin-jwt-demo 
1 2 3 [GIN] 2020/04/18 - 18:29:51 | 200 |    1.502204ms |             ::1 | POST     "/login"  [GIN] 2020/04/18 - 18:30:50 | 401 |     112.029µs |             ::1 | GET      "/auth/hello"  [GIN] 2020/04/18 - 18:32:55 | 200 |     346.218µs |             ::1 | GET      "/auth/hello"  
直接请求401
1 2 3 4 {     "code" : 401,     "message" : "cookie token is empty"  } 
登录返回token
1 2 3 4 5 {     "code" : 200,     "expire" : "2020-04-18T19:29:51+08:00" ,     "token" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1ODcyMDkzOTEsImlkIjoiYWRtaW4iLCJvcmlnX2lhdCI6MTU4NzIwNTc5MX0.o55urrL-qhUqpqEKK8k8KF8yBqrgZo_EtKmuOW1bHnc"  } 
携带token请求
1 2 3 4 5 {     "text" : "Hello World." ,     "userID" : "admin" ,     "userName" : "admin"  } 
go-admin中的使用 这里也就记录别人在项目中是怎么使用的,以及有没有可以学习的地方。
auth.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 package middleware import ( 	config2 "go-admin/config"  	"go-admin/handler"  	jwt "go-admin/pkg/jwtauth"  	"time"  ) func AuthInit() (*jwt.GinJWTMiddleware, error) { 	return  jwt.New(&jwt.GinJWTMiddleware{ 		Realm:           "test zone" , 		Key:             []byte("secret key" ), 		Timeout:         time.Hour, 		MaxRefresh:      time.Hour, 		IdentityKey:     config2.ApplicationConfig.JwtSecret, 		PayloadFunc:     handler.PayloadFunc, 		IdentityHandler: handler.IdentityHandler, 		Authenticator:   handler.Authenticator, 		Authorizator:    handler.Authorizator, 		Unauthorized:    handler.Unauthorized, 		TokenLookup:     "header: Authorization, query: token, cookie: jwt" , 		TokenHeadName:   "Bearer" , 		TimeFunc:        time.Now, 	}) } 
permission.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 package middleware import ( 	"github.com/gin-gonic/gin"  	"go-admin/pkg"  	mycasbin "go-admin/pkg/casbin"  	"go-admin/pkg/jwtauth"  	_ "go-admin/pkg/jwtauth"  	"log"  	"net/http"  ) //权限检查中间件 func AuthCheckRole() gin.HandlerFunc { 	return  func(c *gin.Context) { 		data, _ := c.Get("JWT_PAYLOAD" ) 		v := data.(jwtauth.MapClaims) 		e, err := mycasbin.Casbin() 		pkg.HasError(err,"" ,500) 		//检查权限 		res, err := e.Enforce(v["rolekey" ], c.Request.URL.Path, c.Request.Method) 		log.Println("----------------" , v["rolekey" ], c.Request.URL.Path, c.Request.Method) 			pkg.HasError(err,"" ,500) 		if  res { 			c.Next() 		} else  { 			c.JSON(http.StatusOK, gin.H{ 				"status" : 401, 				"msg" :    "对不起,您没有该接口访问权限,请联系管理员" , 			}) 			c.Abort() 			return  		} 	} } 
router.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 func InitRouter() *gin.Engine { 	// the jwt middleware 	authMiddleware, err := middleware.AuthInit()//初始化 	if  err != nil { 		_ = fmt.Errorf("JWT Error" , err.Error()) 	} 	r.POST("/login" , authMiddleware.LoginHandler)  //框架自带 	// Refresh time can be longer than token timeout 	r.GET("/refresh_token" , authMiddleware.RefreshHandler)//框架自带     apiv1 := r.Group("/api/v1" ) 	{ 		apiv1.GET("/monitor/server" , monitor.ServerInfo) 		...     }     auth := r.Group("/api/v1" ) 	auth.Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())//检测权限 	{ 		auth.GET("/deptList" , system.GetDeptList) 		...     } } 
写到最后发现这里有篇博客写的挺好的,可以看看~https://blog.firerain.me/article/18 
.end