diff --git a/app/admin/router/sys_router.go b/app/admin/router/sys_router.go index b713e4b0..268d4bc4 100644 --- a/app/admin/router/sys_router.go +++ b/app/admin/router/sys_router.go @@ -69,8 +69,15 @@ func sysCheckRoleRouterInit(r *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddle v1 := r.Group("/api/v1") { v1.POST("/login", authMiddleware.LoginHandler) - // Refresh time can be longer than token timeout - v1.GET("/refresh_token", authMiddleware.RefreshHandler) + // GET /api/v1/refresh_token 已移除,原因见 issue #820: + // 该接口用业务 token 即可换取新 token,而续期上限 MaxRefresh 依据的 + // orig_iat 在每次续期时被一并重置,上限永远无法到达 —— token 一旦泄 + // 露即等同于永久访问权。它此前还位于 CasbinExclude 中,任何角色的已 + // 登录用户都能调用,不受权限约束。 + // + // 官方前端从未调用该接口(store 中的 refreshToken action 无人 dispatch), + // 移除不影响正常使用。若确需无感续期,应在 go-admin-core 中区分 + // access token 与 refresh token 后重新实现,而非沿用此路由。 } registerBaseRouter(v1, authMiddleware) } diff --git a/cmd/migrate/migration/version/1786700002000_remove_refresh_token_api.go b/cmd/migrate/migration/version/1786700002000_remove_refresh_token_api.go new file mode 100644 index 00000000..f02936d8 --- /dev/null +++ b/cmd/migrate/migration/version/1786700002000_remove_refresh_token_api.go @@ -0,0 +1,61 @@ +package version + +import ( + "runtime" + + "gorm.io/gorm" + + "go-admin/cmd/migrate/migration" + "go-admin/cmd/migrate/migration/models" + common "go-admin/common/models" +) + +// 清理 GET /api/v1/refresh_token 的残留权限数据。 +// +// 该路由已随 issue #820 的修复移除:它允许用业务 token 换取新 token,而续期 +// 上限 MaxRefresh 依据的 orig_iat 每次续期都被重置,上限永远无法到达。 +// +// 路由虽已删除(请求会返回 404),但已有部署的库中仍残留三类记录:接口登记、 +// 菜单与接口的绑定、Casbin 策略。留着会让「接口管理」列出一个不存在的端点, +// 角色配置里也仍可勾选,造成误解。 +// +// 按 path 匹配而非固定 id —— 使用者若执行过 `server -a` 重新注册接口,id 会 +// 与官方种子数据不同。 +func init() { + _, fileName, _, _ := runtime.Caller(0) + migration.Migrate.SetVersion(migration.GetFilename(fileName), _1786700002000RemoveRefreshTokenApi) +} + +const refreshTokenPath = "/api/v1/refresh_token" + +func _1786700002000RemoveRefreshTokenApi(db *gorm.DB, version string) error { + return db.Transaction(func(tx *gorm.DB) error { + var apiIds []int + if err := tx.Model(&models.SysApi{}). + Where("path = ? AND action = ?", refreshTokenPath, "GET"). + Pluck("id", &apiIds).Error; err != nil { + return err + } + + if len(apiIds) > 0 { + // 先断开绑定,再删接口本身,避免遗留悬空外键 + // 连接表由 GORM many2many 生成,列名为 sys_api_id 而非 api_id + if err := tx.Exec("DELETE FROM sys_menu_api_rule WHERE sys_api_id IN ?", apiIds).Error; err != nil { + return err + } + if err := tx.Where("id IN ?", apiIds).Delete(&models.SysApi{}).Error; err != nil { + return err + } + } + + // casbin_rule 才是 adapter 实际使用的表,策略按路径存储,与 sys_api 的 + // id 无关,因此即使上面没匹配到接口也要清理 + if err := tx.Exec( + "DELETE FROM casbin_rule WHERE ptype = 'p' AND v1 = ?", refreshTokenPath, + ).Error; err != nil { + return err + } + + return tx.Create(&common.Migration{Version: version}).Error + }) +} diff --git a/common/middleware/settings.go b/common/middleware/settings.go index daf8d305..248a640f 100644 --- a/common/middleware/settings.go +++ b/common/middleware/settings.go @@ -24,7 +24,6 @@ var CasbinExclude = []UrlInfo{ {Url: "/api/v1/menuids", Method: "GET"}, {Url: "/api/v1/roleMenuTreeselect/:roleId", Method: "GET"}, {Url: "/api/v1/roleDeptTreeselect/:roleId", Method: "GET"}, - {Url: "/api/v1/refresh_token", Method: "GET"}, {Url: "/api/v1/configKey/:configKey", Method: "GET"}, {Url: "/api/v1/app-config", Method: "GET"}, {Url: "/api/v1/user/profile", Method: "GET"}, diff --git a/config/db-sqlserver.sql b/config/db-sqlserver.sql index 0ba4168c..f73bd7dd 100644 --- a/config/db-sqlserver.sql +++ b/config/db-sqlserver.sql @@ -37,7 +37,6 @@ INSERT INTO sys_api (id, handle, title, path, type, "action", created_at, update (45, 'go-admin/app/admin/apis.SysMenu.GetMenuTreeSelect-fm', '菜单权限列表【角色配菜单使用】', '/api/v1/roleMenuTreeselect/:roleId', 'SYS', 'GET', '2021-05-13 19:59:02.762', '2021-06-17 11:48:40.732', NULL, 0, 0), (46, 'go-admin/app/admin/apis.SysDept.GetDeptTreeRoleSelect-fm', '角色部门结构树【自定义数据权限】', '/api/v1/roleDeptTreeselect/:roleId', 'SYS', 'GET', '2021-05-13 19:59:02.809', '2021-06-17 11:48:40.732', NULL, 0, 0), (47, 'go-admin/app/admin/apis.SysRole.Get-fm', '角色通过id获取', '/api/v1/role/:id', 'BUS', 'GET', '2021-05-13 19:59:02.850', '2021-06-17 11:48:40.732', NULL, 0, 0), -(48, 'github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth.(*GinJWTMiddleware).RefreshHandler-fm', '刷新token', '/api/v1/refresh_token', 'SYS', 'GET', '2021-05-13 19:59:02.892', '2021-06-13 20:53:49.278', NULL, 0, 0), (53, 'go-admin/app/admin/apis.SysConfig.GetPage-fm', '参数列表', '/api/v1/config', 'BUS', 'GET', '2021-05-13 19:59:03.116', '2021-06-17 11:48:40.732', NULL, 0, 0), (54, 'go-admin/app/admin/apis.SysConfig.Get-fm', '参数通过id获取', '/api/v1/config/:id', 'BUS', 'GET', '2021-05-13 19:59:03.157', '2021-06-17 11:48:40.732', NULL, 0, 0), (55, 'go-admin/app/admin/apis.SysConfig.GetSysConfigByKEYForService-fm', '参数通过键名搜索【基础默认配置】', '/api/v1/configKey/:configKey', 'SYS', 'GET', '2021-05-13 19:59:03.198', '2021-06-13 20:53:49.745', NULL, 0, 0), diff --git a/config/db.sql b/config/db.sql index 5c84adf0..b4d03ee6 100644 --- a/config/db.sql +++ b/config/db.sql @@ -35,7 +35,6 @@ INSERT INTO sys_api VALUES (44, 'go-admin/app/admin/apis.SysRole.GetPage-fm', ' INSERT INTO sys_api VALUES (45, 'go-admin/app/admin/apis.SysMenu.GetMenuTreeSelect-fm', '菜单权限列表【角色配菜单使用】', '/api/v1/roleMenuTreeselect/:roleId', 'SYS', 'GET', '2021-05-13 19:59:02.762', '2021-06-17 11:48:40.732', NULL, 0, 0); INSERT INTO sys_api VALUES (46, 'go-admin/app/admin/apis.SysDept.GetDeptTreeRoleSelect-fm', '角色部门结构树【自定义数据权限】', '/api/v1/roleDeptTreeselect/:roleId', 'SYS', 'GET', '2021-05-13 19:59:02.809', '2021-06-17 11:48:40.732', NULL, 0, 0); INSERT INTO sys_api VALUES (47, 'go-admin/app/admin/apis.SysRole.Get-fm', '角色通过id获取', '/api/v1/role/:id', 'BUS', 'GET', '2021-05-13 19:59:02.850', '2021-06-17 11:48:40.732', NULL, 0, 0); -INSERT INTO sys_api VALUES (48, 'github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth.(*GinJWTMiddleware).RefreshHandler-fm', '刷新token', '/api/v1/refresh_token', 'SYS', 'GET', '2021-05-13 19:59:02.892', '2021-06-13 20:53:49.278', NULL, 0, 0); INSERT INTO sys_api VALUES (53, 'go-admin/app/admin/apis.SysConfig.GetPage-fm', '参数列表', '/api/v1/config', 'BUS', 'GET', '2021-05-13 19:59:03.116', '2021-06-17 11:48:40.732', NULL, 0, 0); INSERT INTO sys_api VALUES (54, 'go-admin/app/admin/apis.SysConfig.Get-fm', '参数通过id获取', '/api/v1/config/:id', 'BUS', 'GET', '2021-05-13 19:59:03.157', '2021-06-17 11:48:40.732', NULL, 0, 0); INSERT INTO sys_api VALUES (55, 'go-admin/app/admin/apis.SysConfig.GetSysConfigByKEYForService-fm', '参数通过键名搜索【基础默认配置】', '/api/v1/configKey/:configKey', 'SYS', 'GET', '2021-05-13 19:59:03.198', '2021-06-13 20:53:49.745', NULL, 0, 0);