package common import ( "context" "net/http" "strings" "github.com/gogf/gf/v2/net/ghttp" ) var publicPaths = []string{ "/system-config/login", } // CheckTokenFingerprint 由 kb/service 注入,避免 common → service 循环依赖 var CheckTokenFingerprint func(ctx context.Context, fp string) bool func Auth(r *ghttp.Request) { path := r.URL.Path // 公开路径(精确匹配) for _, p := range publicPaths { if path == p { r.Middleware.Next() return } } // workspace 源文件前缀放行(浏览器下载/预览请求不带 Authorization) if strings.HasPrefix(path, "/workspace/") { r.Middleware.Next() return } // 前端静态资源放行:仅 GET / 与 GET /assets/*(hash 路由下 SPA 只请求这两个路径) if r.Method == http.MethodGet && (path == "/" || strings.HasPrefix(path, "/assets/")) { r.Middleware.Next() return } auth := r.Header.Get("Authorization") if auth == "" || !strings.HasPrefix(auth, "Bearer ") { r.Response.WriteJson(ghttp.DefaultHandlerResponse{ Code: http.StatusUnauthorized, Message: "未登录或登录已过期", }) r.Exit() return } claims, err := ParseToken(auth[7:]) if err != nil { r.Response.WriteJson(ghttp.DefaultHandlerResponse{ Code: http.StatusUnauthorized, Message: "登录已过期,请重新登录", }) r.Exit() return } // 指纹校验:访问令牌被重新生成后,旧会话立即失效 if CheckTokenFingerprint != nil && !CheckTokenFingerprint(r.Context(), claims.TokenFp) { r.Response.WriteJson(ghttp.DefaultHandlerResponse{ Code: http.StatusUnauthorized, Message: "访问令牌已变更,请重新登录", }) r.Exit() return } r.SetCtxVar("role", claims.Role) r.Middleware.Next() } func GetRole(r *ghttp.Request) string { v := r.GetCtxVar("role") if v == nil { return "" } return v.String() }