我正在使用Golang中的GIN和Gin-JWT框架。 到目前为止,到目前为止,我已经能够按照Gin-JWT软件包中的示例使用JWT授权和认证我的REST API。
我现在正在尝试在我的API中实现某种角色。 流程为:
到目前为止,我的主要内容是:
jwtAfp := InitJwtMiddleware(db)
afb := r.Group("api/v1/afb")
afb.Use(jwtAfp.MiddlewareFunc())
afb.GET("/ping", afbController.Ping)
这是使用Gin-JWT的InitJwtMiddleware的
func InitJwtMiddleware(db *gorm.DB) *jwt.GinJWTMiddleware {
return &jwt.GinJWTMiddleware{
Realm: "afb",
Key: []byte("secret pwd"),
Timeout: time.Hour,
MaxRefresh: time.Hour,
PayloadFunc: func(data interface{}) jwt.MapClaims {
if v, ok := data.(*model.User); ok {
return jwt.MapClaims{
"afb": v.ID,
}
}
return jwt.MapClaims{}
},
Authenticator: func(c *gin.Context) (interface{}, error) {
var loginVals login
if err := c.Bind(&loginVals); err != nil {
return "", jwt.ErrMissingLoginValues
}
email := loginVals.Username
password := loginVals.Password
var u model.User
db.Where("email = ?", email).First(&u)
if service.CheckPasswordHash(password, u.Password) {
return &u, nil
}
return nil, jwt.ErrFailedAuthentication
},
Authorizator: func(data interface{}, c *gin.Context) bool {
claims := jwt.ExtractClaims(c)
v, ok := data.(float64)
if ok && v == claims["afb"] {
return true
}
return false
},
Unauthorized: func(c *gin.Context, code int, message string) {
c.JSON(code, gin.H{
"code": code,
"message": message,
})
},
TokenHeadName: "Bearer",
TimeFunc: time.Now,
}
}
我想在Authorizator部分中添加对Role的检查,但是我在如何做到这一点上苦苦挣扎。 我想同时传递InitJwtMiddleware(db)函数,这个函数可以工作,但是我不喜欢为每个ROLE / API“实例化”一个GinJWTMiddleware的想法。或者,如果我可以在中间件中知道稍后将调用哪个函数(控制器),那么我可以确定是否进行授权。但是,即使是这种甜味剂对我来说也很尴尬。我认为会有一个最优雅的解决方案,有什么想法吗?
答案 0 :(得分:1)
您可以尝试以下方法:
https://github.com/kyfk/gin-jwt
这是最简单的auth [orization / entication]库。
VerifyPerm功能可能有助于角色管理。
func main() {
auth, err := jwt.New(jwt.Auth{
SecretKey: []byte("must change here"),
// Authenticator authenticates a request and return jwt.MapClaims
// that contains a user information of the request.
Authenticator: func(c *gin.Context) (jwt.MapClaims, error) {
var loginForm LoginForm
if err := c.ShouldBind(&loginForm); err != nil {
return nil, jwt.ErrorAuthenticationFailed
}
u, ok := authenticate(req.Username, req.Password)
if ok {
return nil, jwt.ErrorAuthenticationFailed
}
return jwt.MapClaims{
"username": u.Username,
"role": u.Role,
}, nil
},
// UserFetcher takes a jwt.MapClaims and return a user object.
UserFetcher: func(c *gin.Context, claims jwt.MapClaims) (interface{}, error) {
username, ok := claims["username"].(string)
if !ok {
return nil, nil
}
return findByUsername(username)
},
})
// some lines
e.Use(jwt.ErrorHandler)
// issue authorization token
e.POST("/login", auth.AuthenticateHandler)
// refresh token expiration
e.POST("/auth/refresh_token", auth.RefreshHandler)
// role management
e.GET("/operator/hello", Operator(auth), SayHello) // this is only for Operator
e.GET("/admin/hello", Admin(auth), SayHello) // this is only for Admin
}
func Operator(m jwt.Auth) gin.HandlerFunc {
return m.VerifyPerm(func(claims jwt.MapClaims) bool {
return role(claims).IsOperator()
})
}
func Admin(m jwt.Auth) gin.HandlerFunc {
return m.VerifyPerm(func(claims jwt.MapClaims) bool {
return role(claims).IsAdmin()
})
}