You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
88 lines
2.4 KiB
Smarty
88 lines
2.4 KiB
Smarty
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
|
|
}
|