ServiceStack中Credentials与Jwt认证提供者冲突问题求助
多认证提供者冲突问题排查
认证配置代码
using System.Reflection; using PaymentGatewayApi.Common; using ServiceStack.Auth; using ServiceStack.Logging; [assembly: HostingStartup(typeof(ConfigureAuth))] namespace PaymentGatewayApi; public class ConfigureAuth : IHostingStartup { private static readonly ILog Logger = LogManager.GetLogger(MethodBase.GetCurrentMethod()?.DeclaringType); public void Configure(IWebHostBuilder builder) => builder .ConfigureAppHost(appHost => { appHost.Plugins.Add(new AuthFeature(() => new AuthUserSession(), [ new CredentialsAuthProvider(appHost.AppSettings), new JwtAuthProvider(appHost.AppSettings), new JwtAuthProviderReader(appHost.AppSettings) { PopulateSessionFilter = (s, p, r) => { if (p.TryGetValue(ApplicationConstants.ScopeKey, out var scopes)) { s.Roles = scopes.FromJson<List<string>>(); Logger.Info($"Registered scopes: {s.Roles.ToJsv()}"); } // 省略其他代码 r.SetItem(ApplicationConstants.RequestClientIdKey, s.UserName); }, UseTokenCookie = false } ]) { MaxLoginAttempts = appHost.AppSettings.Get("Authentication:MaxLoginAttempts", 5), IncludeDefaultLogin = false, SessionExpiry = TimeSpan.FromMinutes(appHost.AppSettings.Get("Session:MinutesExpiration", 30)), }); appHost.Plugins.Add(new RegistrationFeature()); Logger.Info("Registered Authentication."); }); }
数据库依赖配置代码
// User repository var authRepo = new OrmLiteAuthRepository<User, UserOAuthDetail>( container.Resolve<IDbConnectionFactory>()) { UseDistinctRoleTables = false }; container.Register<IUserAuthRepository>(authRepo); container.Register<IAuthRepository>(authRepo);
问题现象
- 执行凭证登录时,返回错误:
PrivateKey required to use: RS256,疑惑凭证登录流程为何需要查找私钥 - 执行JWT登录时,返回错误:
The input string 'cf2c40f3-9cd9-419c-916b-2e4f93821a22' was not in a correct format,疑惑JWT流程为何会去数据库验证令牌数据
问题原因分析与排查方向
凭证登录触发RS256私钥检查的原因
同时注册JwtAuthProvider和JwtAuthProviderReader时,JwtAuthProvider默认会在用户登录成功后生成JWT响应返回给客户端。当使用凭证登录(CredentialsAuth)成功后,AuthFeature会按注册顺序执行认证提供者的逻辑,JwtAuthProvider需要私钥来签名RS256算法的JWT,因此即使是凭证登录流程,也会触发私钥检查。
排查方向:
- 检查AppSettings中是否配置了JWT私钥(
JwtPrivateKey),若使用RS256算法必须配置RSA私钥;若无需RS256,可切换为HS256算法,只需配置JwtSecret - 若不需要在凭证登录后返回JWT,可移除
JwtAuthProvider,仅保留JwtAuthProviderReader用于验证客户端传入的JWT令牌,凭证登录的会话管理使用ServiceStack默认Session即可
JWT登录触发数据库验证的原因
JwtAuthProviderReader默认会尝试将JWT令牌中的用户标识与数据库中的用户记录关联,若令牌中的用户标识(如sub字段)格式与数据库UserAuth.Id类型不匹配(例如数据库Id为整数类型,而令牌中是UUID字符串),就会触发类型转换报错。此外,若未正确配置SkipSessionCreation等属性,也会触发数据库查询逻辑。
排查方向:
- 检查
JwtAuthProviderReader的配置,确认SkipSessionCreation是否设置为true(若无需创建服务端Session,可跳过数据库查询) - 核对JWT令牌payload中的用户标识字段(如
sub)格式,确保与User实体类中Id字段的类型一致(例如Id是Guid则令牌传递Guid,是int则传递整数) - 启用ServiceStack Debug级日志,查看JWT验证流程的调用栈,定位触发数据库查询的具体代码位置,确认是否是配置或逻辑导致的不必要查询
内容的提问来源于stack exchange,提问作者Carlos Ramírez
相关产品推荐
相关产品推荐

