package middleware import ( "blazing/cool" "blazing/modules/base/config" "github.com/gogf/gf/v2/container/garray" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/net/ghttp" "github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/util/gconv" "github.com/golang-jwt/jwt/v4" ) // 本类接口无需权限验证 func BaseAuthorityMiddlewareOpen(r *ghttp.Request) { r.SetCtxVar("AuthOpen", true) r.Middleware.Next() } // 本类接口无需权限验证,只需登录验证 func BaseAuthorityMiddlewareComm(r *ghttp.Request) { r.SetCtxVar("AuthComm", true) r.Middleware.Next() } // 其余接口需登录验证同时需要权限验证 func BaseAuthorityMiddleware(r *ghttp.Request) { // g.Dump(r) // g.Dump(r.GetHeader("Authorization")) var ( statusCode = 200 ctx = r.GetCtx() ) url := r.URL.String() // 无需登录验证 AuthOpen := r.GetCtxVar("AuthOpen", false) if AuthOpen.Bool() { r.Middleware.Next() return } tokenString := r.GetHeader("Authorization") token, err := jwt.ParseWithClaims(tokenString, &cool.Claims{}, func(token *jwt.Token) (interface{}, error) { return []byte(config.Config.Jwt.Secret), nil }) if err != nil { cool.Loger.Error(ctx, "BaseAuthorityMiddleware", err) statusCode = 401 r.Response.WriteStatusExit(statusCode, g.Map{ "code": 1001, "message": "登陆失效~", }) } if !token.Valid { cool.Loger.Error(ctx, "BaseAuthorityMiddleware", "token invalid") statusCode = 401 r.Response.WriteStatusExit(statusCode, g.Map{ "code": 1001, "message": "登陆失效~", }) } admin := token.Claims.(*cool.Claims) // 将用户信息放入上下文 r.SetCtxVar("admin", admin) cachetoken, _ := cool.CacheManager.Get(ctx, "admin:token:"+gconv.String(admin.UserId)) rtoken := cachetoken.String() // 超管拥有所有权限 if admin.UserId == 10001 && !admin.IsRefresh { if tokenString != rtoken && config.Config.Jwt.Sso { cool.Loger.Error(ctx, "BaseAuthorityMiddleware", "token invalid") statusCode = 401 r.Response.WriteStatusExit(statusCode, g.Map{ "code": 1001, "message": "登陆失效~", }) } else { r.Middleware.Next() return } } // 只验证登录不验证权限的接口 AuthComm := r.GetCtxVar("AuthComm", false) if AuthComm.Bool() { r.Middleware.Next() return } // 如果传的token是refreshToken则校验失败 if admin.IsRefresh { cool.Loger.Error(ctx, "BaseAuthorityMiddleware", "token invalid") statusCode = 401 r.Response.WriteStatusExit(statusCode, g.Map{ "code": 1001, "message": "登陆失效~", }) } // 判断密码版本是否正确 passwordV, _ := cool.CacheManager.Get(ctx, "admin:passwordVersion:"+gconv.String(admin.UserId)) if passwordV.Int32() != *admin.PasswordVersion { cool.Loger.Error(ctx, "BaseAuthorityMiddleware", "passwordV invalid") statusCode = 401 r.Response.WriteStatusExit(statusCode, g.Map{ "code": 1001, "message": "登陆失效~", }) } // 如果rtoken为空 if rtoken == "" { cool.Loger.Error(ctx, "BaseAuthorityMiddleware", "rtoken invalid") statusCode = 401 r.Response.WriteStatusExit(statusCode, g.Map{ "code": 1001, "message": "登陆失效~", }) } // 如果rtoken不等于token 且 sso 未开启 if tokenString != rtoken && !config.Config.Jwt.Sso { cool.Loger.Error(ctx, "BaseAuthorityMiddleware", "token invalid") statusCode = 401 r.Response.WriteStatusExit(statusCode, g.Map{ "code": 1001, "message": "登陆失效~", }) } // 从缓存获取perms permsCache, _ := cool.CacheManager.Get(ctx, "admin:perms:"+gconv.String(admin.UserId)) // 转换为数组 permsVar := permsCache.Strings() // 转换为garray perms := garray.NewStrArrayFrom(permsVar) // 如果perms为空 if perms.Len() == 0 { cool.Loger.Error(ctx, "BaseAuthorityMiddleware", "perms invalid") statusCode = 403 r.Response.WriteStatusExit(statusCode, g.Map{ "code": 1001, "message": "登录失效或无权限访问~", }) } // 去除url后面的参数,使用字符串分割方法,若长度等于2,则说明有参数,则我们将改写url值进行权限比对 parts := gstr.Split(url, "?") if len(parts) == 2 { url = parts[0] } //url 转换为数组 urls := gstr.Split(url, "/") // 去除第一个空字符串和admin urls = urls[2:] // 以冒号连接成新字符串url url = gstr.Join(urls, ":") // 如果perms中不包含url 则无权限 if !perms.ContainsI(url) { cool.Loger.Error(ctx, "BaseAuthorityMiddleware", "perms invalid") statusCode = 403 r.Response.WriteStatusExit(statusCode, g.Map{ "code": 1001, "message": "登录失效或无权限访问~", }) } // 上面写逻辑 r.Middleware.Next() }