package middleware import ( "net/http" "strings" "github.com/casbin/casbin/v2" "github.com/zeromicro/go-zero/core/stores/redis" "git.noahlan.cn/noahlan/ntools-go/core/nlog" "git.noahlan.cn/noahlan/ntools-go/zero/statusz" "git.noahlan.cn/noahlan/ntool-biz/core/nstatus" {{if .useTrans}} "git.noahlan.cn/noahlan/ntools-go/core/i18n"{{end}} ) type AuthorityMiddleware struct { Cbn *casbin.Enforcer Rds *redis.Redis } func NewAuthorityMiddleware(cbn *casbin.Enforcer, rds *redis.Redis) *AuthorityMiddleware { return &AuthorityMiddleware{ Cbn: cbn, Rds: rds, } } func (m *AuthorityMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { {{if .useTrans}}const transErr = true{{else}}const transErr = false{{end}} // get the path obj := r.URL.Path // get the method act := r.Method // get the role id roleIds := r.Context().Value("roleIds").(string) // check jwt blacklist jwtResult, err := m.Rds.Get("token_" + r.Header.Get("Authorization")) if err != nil { nlog.Errorw("redis error in jwt", nlog.Field("detail", err.Error())) statusz.ResponseHandler(r, w, transErr, nil, nstatus.NewApiInternalErr(err.Error())) return } if jwtResult == "1" { nlog.Errorw("token in blacklist", nlog.Field("detail", r.Header.Get("Authorization"))) statusz.ResponseHandler(r, w, transErr, nil, nstatus.NewApiErrWithCode(http.StatusUnauthorized)) return } result := batchCheck(m.Cbn, roleIds, act, obj) if result { nlog.Infow("HTTP/HTTPS Request", nlog.Field("UUID", r.Context().Value("userId").(string)), nlog.Field("path", obj), nlog.Field("method", act)) next(w, r) return } else { nlog.Errorw("the role is not permitted to access the API", nlog.Field("roleIds", roleIds), nlog.Field("path", obj), nlog.Field("method", act)) statusz.ResponseHandler(r, w, transErr, nil, nstatus.NewApiForbiddenErr("common.permissionDeny")) return } } } func batchCheck(cbn *casbin.Enforcer, roleIds, act, obj string) bool { var checkReq [][]any for _, v := range strings.Split(roleIds, ",") { checkReq = append(checkReq, []any{v, obj, act}) } result, err := cbn.BatchEnforce(checkReq) if err != nil { nlog.Errorw("Casbin enforce error", nlog.Field("detail", err.Error())) return false } for _, v := range result { if v { return true } } return false }