mirror of
https://github.com/go-admin-team/go-admin.git
synced 2026-09-24 19:17:43 +00:00
Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
be3c4452e3 | ||
|
|
5b01c9ada8 | ||
|
|
ffd82a6a10 |
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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: 这里可存放业务路由,里边并无实际路由只有演示代码
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/go-admin-team/go-admin-core/v2/sdk"
|
||||
"github.com/go-admin-team/go-admin-core/v2/sdk/config"
|
||||
"github.com/go-admin-team/go-admin-core/v2/sdk/runtime"
|
||||
)
|
||||
|
||||
// freshRuntime hands the test its own Runtime and puts the old one back, the
|
||||
// same pattern cmd/api/server_test.go uses: sdk.Runtime is a process-wide
|
||||
// singleton, and a test that registers into it would otherwise leak state
|
||||
// into every other test in the binary.
|
||||
func freshRuntime(t *testing.T) {
|
||||
t.Helper()
|
||||
previous := sdk.Runtime
|
||||
t.Cleanup(func() { sdk.Runtime = previous })
|
||||
sdk.Runtime = runtime.NewConfig()
|
||||
}
|
||||
|
||||
// TestInitMiddlewareRegistersUsableJwtHandlerFunc is the reverse proof for
|
||||
// hoisting the JWT instance's construction into InitMiddleware:
|
||||
// sdk.Runtime.GetHandlerFunc(JwtTokenCheck) must hand back ok=true and a
|
||||
// non-nil gin.HandlerFunc, not just something GetMiddleware can return as an
|
||||
// untyped interface{}.
|
||||
//
|
||||
// Before this change, InitMiddleware registered the unbound method
|
||||
// expression (*jwt.GinJWTMiddleware).MiddlewareFunc under this key - a value
|
||||
// with no receiver bound to it, which is not a gin.HandlerFunc no matter how
|
||||
// a caller asserts its type. Reverting the registration below to that
|
||||
// expression makes GetHandlerFunc report ok=false; it does not fail to
|
||||
// compile, because (*jwt.GinJWTMiddleware).MiddlewareFunc has a well-formed,
|
||||
// unrelated method-expression type that SetMiddleware's interface{} param
|
||||
// happily accepts.
|
||||
func TestInitMiddlewareRegistersUsableJwtHandlerFunc(t *testing.T) {
|
||||
freshRuntime(t)
|
||||
|
||||
previousSecret := config.JwtConfig.Secret
|
||||
config.JwtConfig.Secret = "test-secret-key"
|
||||
t.Cleanup(func() { config.JwtConfig.Secret = previousSecret })
|
||||
|
||||
gin.SetMode(gin.TestMode)
|
||||
InitMiddleware(gin.New())
|
||||
|
||||
h, ok := sdk.Runtime.GetHandlerFunc(JwtTokenCheck)
|
||||
if !ok {
|
||||
t.Fatal("GetHandlerFunc(JwtTokenCheck) reported ok=false after InitMiddleware ran")
|
||||
}
|
||||
if h == nil {
|
||||
t.Fatal("GetHandlerFunc(JwtTokenCheck) reported ok=true but returned a nil handler")
|
||||
}
|
||||
}
|
||||
|
||||
// TestInitMiddlewareBuildsOneSharedJwtInstance locks down the fix for the
|
||||
// four-instances problem: GetAuthMiddleware must return the very instance
|
||||
// InitMiddleware built and handed to sdk.Runtime, not a lookalike built
|
||||
// separately by whichever caller asks first.
|
||||
func TestInitMiddlewareBuildsOneSharedJwtInstance(t *testing.T) {
|
||||
freshRuntime(t)
|
||||
|
||||
previousSecret := config.JwtConfig.Secret
|
||||
config.JwtConfig.Secret = "test-secret-key"
|
||||
t.Cleanup(func() { config.JwtConfig.Secret = previousSecret })
|
||||
|
||||
gin.SetMode(gin.TestMode)
|
||||
InitMiddleware(gin.New())
|
||||
|
||||
shared := GetAuthMiddleware()
|
||||
if shared == nil {
|
||||
t.Fatal("GetAuthMiddleware returned nil after InitMiddleware ran")
|
||||
}
|
||||
if shared != authMiddleware {
|
||||
t.Error("GetAuthMiddleware did not return the package-level instance InitMiddleware built")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user