Skip to content

ServerConfig ​

*di.ServerConfig 是宿主向 wicket 注入数据、存储和扩展实现的唯一入口。本页按用途分组列出 v0.1.4 的全部导出方法(di/server_config.go),并说明各方法何时被读取——这决定了运行中修改它是否生效。

go
root, err := di.NewRoot()
if err != nil { /* ... */ }
defer root.Close()

cfg := root.ServerConfig()
// ... 一系列 Set*
cfg.Freeze() // 装配完成

ServerConfig 的每个 SetX 都有对应的读取方法 X(),读取方法供容器内部使用,宿主一般不需要调用,下文不再逐一列出。

Set 与 Provider 变体 ​

大多数注入缝同时提供两种写法:

  • SetX(value):直接给值。内部等价于 SetXProvider(func() T { return value })。
  • SetXProvider(func() T):给一个函数,由容器在需要时调用。

两者的差别不在写法,而在容器调用该函数的时机。v0.1.4 中分为三类:

类别涉及的方法何时调用 Provider实际含义
配置数据Clients、IdentityScopes、ApiResources、ApiScopes、SigningCredentialStores、ValidationKeysStores每次解析相关服务时(瞬态)Provider 可以返回最新数据,实现不重启的热更新
存储注入缝除授权参数消息存储外的 10 个 store首次使用时调用一次,结果被缓存到进程结束Provider 只是“延迟构造”;之后再调用 SetX 不会生效
授权参数消息存储AuthorizationParametersMessageStore每次解析时返回 nil 表示不使用存储(见下文)

下面的片段已编译运行验证:

go
// 客户端列表可热更新:每次解析 ClientStore 都会调用这个函数
var clients atomic.Pointer[[]*models.Client]
initial := []*models.Client{}
clients.Store(&initial)
cfg.SetClientsProvider(func() []*models.Client { return *clients.Load() })

// 存储注入缝:首次使用时调用一次,结果被缓存
cfg.SetSessionStoreProvider(func() session.Store {
    return session.NewMemoryStore(wallClock{}) // 换成你的持久化适配器
})

热更新时注意

配置数据类 Provider 在请求路径上被频繁调用(ClientStore 每次解析都会重建索引并做重复 id 校验),函数本身要快且并发安全,不要在里面查数据库;在后台刷新一份快照、Provider 只读快照即可。

日志 ​

方法说明
SetLogger(*slog.Logger)设置容器内部组件使用的 logger

v0.1.4 已知问题:SetLogger 对容器内部组件不生效

容器内部的 *slog.Logger 在 di.NewRoot() 执行时就已确定。而 ServerConfig 是由 NewRoot() 创建的,宿主不可能在此之前调用 SetLogger,所以内部组件实际使用的总是默认 logger:JSON 格式、Debug 级别、带源码位置、写到标准输出。server.WithLogger(...) 只影响 Server 自身的少量日志。

实测:快速开始示例设置了文本格式的 logger,但端点路由、客户端校验等内部日志仍以 JSON 形式出现在 stdout。宿主目前无法调整这一路日志的级别。v0.1.4 的部分日志可能包含敏感请求参数,生产部署时请把 stdout 接入日志系统,在采集侧按级别过滤、删除敏感字段,并避免把原始日志发往不受信任的系统,详见 日志与可观测性。

客户端与资源 ​

方法类型说明
SetClients / SetClientsProvider[]*models.Client客户端注册表。内部包一层校验后作为 ClientStore
SetIdentityScopes / SetIdentityScopesProvider[]*models.IdentityResource身份资源(openid、profile 等)
SetApiResources / SetApiResourcesProvider[]*models.ApiResourceAPI 资源;内省端点用它的名称和 ApiSecrets 认证调用方
SetApiScopes / SetApiScopesProvider[]*models.ApiScopeAPI scope

v0.1.4 的客户端与资源只能通过这几个方法注入,没有可替换的 ClientStore / ResourceStore 注入缝。需要从数据库加载时,用 Provider 变体返回快照。字段含义见客户端与资源。

签名与验证密钥 ​

方法类型说明
SetSigningCredentialStores / SetSigningCredentialStoresProvider[]storage.SigningCredentialStore签名凭据来源
SetValidationKeysStores / SetValidationKeysStoresProvider[]storage.ValidationKeysStore验证公钥来源,合并后发布到 JWKS
SetRecordStore / SetRecordStoreProviderkeymgmt.RecordStore开启自动密钥管理(opts.KeyManagement.Enabled,默认开启)时,密钥记录的持久化位置

注意方法名是 SetRecordStore,不是 SetKeyRecordStore。两种密钥来源如何取舍见签名密钥。

存储注入缝 ​

方法(均有 *Provider 变体)接口未注入且允许回退时
SetAuthorizationCodeStorestorage.AuthorizationCodeStore内存实现 + 警告日志
SetRefreshTokenStorestorage.RefreshTokenStore同上
SetReferenceTokenStorestorage.ReferenceTokenStore同上
SetUserConsentStorestorage.UserConsentStore同上
SetPersistedGrantStorestorage.PersistedGrantStore同上
SetDeviceFlowStorestorage.DeviceFlowStore同上
SetBackchannelAuthenticationRequestStorestorage.BackchannelAuthenticationRequestStore同上
SetSessionStoresession.Store同上
SetDistributedCacheservices.DistributedCache同上
SetRecordStorekeymgmt.RecordStore同上
SetAuthorizationParametersMessageStorestorage.AuthorizationParametersMessageStore不回退:不使用存储,授权参数直接放在回调 URL 的查询串里

以上 11 项都计入 Freeze() 的完整性检查。接口方法与契约见存储端口。

资源释放:root.Close() 会按构造的逆序关闭已经实际用到的 store;若你的适配器实现了 io.Closer,其 Close() 会被调用。从未被使用的 store 不会被构造也不会被关闭。授权参数消息存储例外——它不经容器包装,由宿主自己负责关闭。

扩展点 ​

方法作用未设置时
SetProfileProvider(func() services.ProfileService)提供用户资料:令牌与 userinfo 中的 claims(GetProfileData)、用户是否仍有效(IsActive)。每次解析时调用,返回 nil 则使用默认实现默认实现不添加任何 claim,且 IsActive 恒为 true。需要 name、email 等用户 claim 时必须注入
SetResourceOwnerValidator(validators.ResourceOwnerPasswordValidator)启用 password 授权并校验用户名密码一律拒绝(NotSupportedResourceOwnerPasswordValidator),发现文档也不公布 password
SetBackchannelAuthenticationUserValidator(validators.BackchannelAuthenticationUserValidator)CIBA 请求中根据 login_hint 等定位用户默认实现仅供开发联调,不会解析或核验用户提示——生产环境必须注入自己的实现
SetAuthenticationHandlerProvider(scheme, func(godi.Provider) auth.Handler)为某个认证方案名提供 handler 工厂,覆盖内置注册使用内置 handler,详见身份接入概览
SetExternalFailurePath(string)外部登录失败时的重定向路径空字符串(不重定向)
SetBackChannelLogoutHttpClient(*http.Client)后端通道登出通知所用的 HTTP 客户端nil
SetBackchannelAuthenticationNotificationHttpClient(*http.Client)CIBA 通知所用的 HTTP 客户端http.DefaultClient(无超时)

后端通道登出通知在 v0.1.4 不会发送

负责发送通知的 BackchannelLogoutService.SendLogoutNotificationsAsync 目前是空实现,直接返回 nil,所以 SetBackChannelLogoutHttpClient 暂时没有可观察的效果——尽管发现文档声明了 backchannel_logout_supported: true。依赖后端通道登出的 RP 需要另行处理,参见会话与登出。

CIBA 通知客户端默认是没有超时的 http.DefaultClient,建议注入一个设置了超时的 *http.Client。

生命周期 ​

方法说明
AllowInMemoryFallback()声明“未注入的存储可以回退到内存实现”。仅用于本地开发与测试
Freeze()标记装配完成。若未调用 AllowInMemoryFallback(),逐项检查上表 11 个存储注入缝,任一未注入即 panic
Frozen() bool是否已调用过 Freeze()

未调用 AllowInMemoryFallback() 时的实测 panic 信息:

text
panic: store seam "authorization parameters message store" not injected by host and in-memory fallback not declared

几点说明:

  • 生产装配应当不调用 AllowInMemoryFallback(),让漏注入在启动时暴露。多副本部署下,任何一个存储落在进程内存里都会导致跨节点请求随机失败。
  • 调用 Freeze() 之后,每个存储在首次使用时还会再做一次已冻结检查;但如果从未调用 Freeze(),这项检查不会触发,未注入的存储会静默回退到内存。所以请总是调用 Freeze()。
  • Freeze() 不会锁住各个 Set* 方法——之后调用它们不会报错,但存储类注入缝一旦被使用就不再重新读取。请把所有注入集中在 Freeze() 之前、开始服务之前完成。

相关阅读 ​

以 Apache License 2.0 发布 · 文档内容 © 2026 Wicket 作者