diff --git a/app/admin/router/init_router.go b/app/admin/router/init_router.go index 991965b7..83c080bc 100644 --- a/app/admin/router/init_router.go +++ b/app/admin/router/init_router.go @@ -25,11 +25,9 @@ func InitRouter() { os.Exit(-1) } - // the jwt middleware - authMiddleware, err := common.AuthInit() - if err != nil { - log.Fatalf("JWT Init Error, %s", err.Error()) - } + // the jwt middleware: shared instance InitMiddleware built at startup, + // not one built here per module (see common/middleware.GetAuthMiddleware). + authMiddleware := common.GetAuthMiddleware() // 注册系统路由 InitSysRouter(r, authMiddleware) diff --git a/app/demo/router/router.go b/app/demo/router/router.go index d994ed46..e7ff76e1 100644 --- a/app/demo/router/router.go +++ b/app/demo/router/router.go @@ -33,11 +33,9 @@ func InitRouter() { os.Exit(-1) } - // the jwt middleware - authMiddleware, err := common.AuthInit() - if err != nil { - log.Fatalf("JWT Init Error, %s", err.Error()) - } + // the jwt middleware: shared instance InitMiddleware built at startup, + // not one built here per module (see common/middleware.GetAuthMiddleware). + authMiddleware := common.GetAuthMiddleware() // 注册业务路由 InitBusinessRouter(r, authMiddleware) diff --git a/app/jobs/router/init_router.go b/app/jobs/router/init_router.go index a0fe10cb..4f0521bd 100644 --- a/app/jobs/router/init_router.go +++ b/app/jobs/router/init_router.go @@ -26,10 +26,9 @@ func InitRouter() { os.Exit(-1) } - authMiddleware, err := common.AuthInit() - if err != nil { - log.Fatalf("JWT Init Error, %s", err.Error()) - } + // the jwt middleware: shared instance InitMiddleware built at startup, + // not one built here per module (see common/middleware.GetAuthMiddleware). + authMiddleware := common.GetAuthMiddleware() // 注册业务路由 initRouter(r, authMiddleware) diff --git a/app/other/router/init_router.go b/app/other/router/init_router.go index 9c75a1df..b25a297a 100644 --- a/app/other/router/init_router.go +++ b/app/other/router/init_router.go @@ -25,10 +25,9 @@ func InitRouter() { os.Exit(-1) } // the jwt middleware - authMiddleware, err := common.AuthInit() - if err != nil { - log.Fatalf("JWT Init Error, %s", err.Error()) - } + // the jwt middleware: shared instance InitMiddleware built at startup, + // not one built here per module (see common/middleware.GetAuthMiddleware). + authMiddleware := common.GetAuthMiddleware() // 注册业务路由 // TODO: 这里可存放业务路由,里边并无实际路由只有演示代码 diff --git a/common/middleware/auth.go b/common/middleware/auth.go index caeb9baa..08efba33 100644 --- a/common/middleware/auth.go +++ b/common/middleware/auth.go @@ -3,11 +3,19 @@ package middleware import ( "time" - "github.com/go-admin-team/go-admin-core/v2/sdk/config" jwt "github.com/go-admin-team/go-admin-core/v2/jwtauth" + log "github.com/go-admin-team/go-admin-core/v2/logger" + "github.com/go-admin-team/go-admin-core/v2/sdk/config" "go-admin/common/middleware/handler" ) +// authMiddleware is the single JWT middleware instance the whole process +// shares. InitMiddleware builds it once, before any module registers its +// routes; GetAuthMiddleware is how a module gets it back instead of calling +// AuthInit itself and building another, functionally-equivalent-but-distinct +// instance. +var authMiddleware *jwt.GinJWTMiddleware + // AuthInit jwt验证new func AuthInit() (*jwt.GinJWTMiddleware, error) { timeout := time.Hour @@ -33,4 +41,23 @@ func AuthInit() (*jwt.GinJWTMiddleware, error) { TimeFunc: time.Now, }) -} \ No newline at end of file +} + +// GetAuthMiddleware returns the shared JWT middleware instance InitMiddleware +// built at startup. Application modules (app/admin, app/jobs, app/other, +// app/demo) call this instead of AuthInit so their router chains - which +// still need the instance itself for authMiddleware.MiddlewareFunc() and +// authMiddleware.LoginHandler, not just the bound closure registered under +// sdk.Runtime's JwtTokenCheck key - end up using the same instance the host +// registered, rather than one each. +// +// It fails loudly instead of returning nil: an InitRouter that runs before +// InitMiddleware has a real startup-ordering bug, not a case to paper over +// with a nil *jwt.GinJWTMiddleware that would panic much further down the +// call chain with a far less useful stack trace. +func GetAuthMiddleware() *jwt.GinJWTMiddleware { + if authMiddleware == nil { + log.Fatal("JWT middleware not initialized; InitMiddleware must run before any module's InitRouter") + } + return authMiddleware +} diff --git a/common/middleware/init.go b/common/middleware/init.go index 96e93262..947c7e56 100644 --- a/common/middleware/init.go +++ b/common/middleware/init.go @@ -2,15 +2,20 @@ package middleware import ( "github.com/gin-gonic/gin" - jwt "github.com/go-admin-team/go-admin-core/v2/jwtauth" + log "github.com/go-admin-team/go-admin-core/v2/logger" "github.com/go-admin-team/go-admin-core/v2/sdk" + "github.com/go-admin-team/go-admin-core/v2/sdk/runtime" "go-admin/common/actions" ) +// These alias core's own constants (see sdk/runtime.GetHandlerFunc's contract +// doc, section 9) rather than redeclaring the same three strings, so a typo +// here can no longer split registration and lookup into two different keys +// that both happen to compile. const ( - JwtTokenCheck string = "JwtToken" - RoleCheck string = "AuthCheckRole" - PermissionCheck string = "PermissionAction" + JwtTokenCheck = runtime.JwtTokenCheck + RoleCheck = runtime.RoleCheck + PermissionCheck = runtime.PermissionCheck ) func InitMiddleware(r *gin.Engine) { @@ -29,7 +34,26 @@ func InitMiddleware(r *gin.Engine) { r.Use(Secure) // 链路追踪 //r.Use(middleware.Trace()) - sdk.Runtime.SetMiddleware(JwtTokenCheck, (*jwt.GinJWTMiddleware).MiddlewareFunc) + + // Build the shared JWT middleware instance here, before any module + // registers routes (initRouter runs ahead of runStartupHooks, which is + // what invokes each module's InitRouter - see cmd/api/server.go). Doing + // it once here, instead of once per module via AuthInit, is what makes + // GetAuthMiddleware and sdk.Runtime.GetHandlerFunc(JwtTokenCheck) both + // resolve to a single, meaningful instance instead of "whichever module + // happened to initialize last". + // + // SetMiddleware must be given a bound closure (authMiddleware.MiddlewareFunc()), + // not the unbound method expression (*jwt.GinJWTMiddleware).MiddlewareFunc: + // the latter has no receiver bound to it, so GetHandlerFunc's type + // assertion to gin.HandlerFunc always fails for it. + var err error + authMiddleware, err = AuthInit() + if err != nil { + // A process with no JWT middleware must not start serving requests. + log.Fatalf("JWT Init Error, %s", err.Error()) + } + sdk.Runtime.SetMiddleware(JwtTokenCheck, authMiddleware.MiddlewareFunc()) sdk.Runtime.SetMiddleware(RoleCheck, AuthCheckRole()) sdk.Runtime.SetMiddleware(PermissionCheck, actions.PermissionAction()) }