Files
go-admin/common/middleware/init.go
zhangwenjian 5b01c9ada8 fix🐛: build the shared jwt middleware instance once in InitMiddleware
Four modules each called AuthInit and built their own instance, so which
one Runtime handed back was decided by whichever module initialised last.
The JwtToken key was also registered as an unbound method expression,
which GetHandlerFunc's type assertion can never match - the key was
registered and unusable at the same time.

The instance is now built once here and registered as a bound closure.
Modules read it back through GetAuthMiddleware, which is fatal rather
than nil when called before InitMiddleware has run: a process without a
JWT middleware should not reach the point of serving a request.

Only one call site needs the instance itself rather than the handler
(admin's /login, for LoginHandler); the thirty-odd MiddlewareFunc() call
sites are unchanged.

Claude-Session: https://claude.ai/code/session_01HPTAw8b8tAdFNFn8rKdPYx
2026-09-05 10:26:54 +08:00

60 lines
2.2 KiB
Go

package middleware
import (
"github.com/gin-gonic/gin"
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 = runtime.JwtTokenCheck
RoleCheck = runtime.RoleCheck
PermissionCheck = runtime.PermissionCheck
)
func InitMiddleware(r *gin.Engine) {
r.Use(DemoEvn())
// 数据库链接
r.Use(WithContextDb)
// 日志处理
r.Use(LoggerToFile())
// 自定义错误处理
r.Use(CustomError)
// NoCache is a middleware function that appends headers
r.Use(NoCache)
// 跨域处理
r.Use(Options)
// Secure is a middleware function that appends security
r.Use(Secure)
// 链路追踪
//r.Use(middleware.Trace())
// 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())
}