负载平衡器 "Invalid HTTP request for token endpoint"
Load Balancer "Invalid HTTP request for token endpoint"
负载均衡器后面的 IdentityServer 有问题,
需要说明的是,如果我使用的是直接 ip,一切都会按预期工作。
目前我在 LB 上有一个 SSL 配置,它带有一个有效的证书,可以重定向到 2 Linux 台机器上托管的 HTTP docker 引擎。
我在我的客户端上使用 MVC 混合流:
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
AuthenticationScheme = "oidc",
SignInScheme = "Cookies",
Authority = settings.Server,
RequireHttpsMetadata = "false",
ClientId = "MyMvcClient",
ClientSecret = "MyMvcSuperPassword",
ResponseType = "code id_token",
GetClaimsFromUserInfoEndpoint = true,
SaveTokens = true,
TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = JwtClaimTypes.Name,
RoleClaimType = JwtClaimTypes.Role,
},
Events = new OpenIdConnectEvents()
{
OnRemoteFailure = context =>
{
context.Response.Redirect("/error");
context.HandleResponse();
return Task.FromResult(0);
}
},
"Scope": { "openid", "profile", "email", "myclient", "offline_access" }
});
在服务器端,我有以下设置:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<IdentityDbContext>(builder);
services.AddIdentity<ApplicationUser, ApplicationRole>()
.AddEntityFrameworkStores<IdentityDbContext, Guid>()
.AddUserStore<UserStore<ApplicationUser, ApplicationRole, IdentityDbContext, Guid>>()
.AddRoleStore<RoleStore<ApplicationRole, IdentityDbContext, Guid>>()
.AddUserManager<LdapUserManager>()
.AddSignInManager<LdapSignInManager>()
.AddDefaultTokenProviders()
.AddIdentityServerUserClaimsPrincipalFactory();
...
string redisSettings = $"{redisHost}:{redisPort},ssl={redisSsl},abortConnect={redisAbortConnect},password={redisPassword}";
services.AddDataProtection().PersistKeysToRedis(redis, redisKey);
...
// Adds IdentityServer
services.AddIdentityServer()
.AddSigningCredential(new X509Certificate2("IdentityServerAuth.pfx"))
.AddConfigurationStore(builder)
.AddOperationalStore(builder)
.AddAspNetIdentity<ApplicationUser>()
.AddProfileService<IdentityProfileService>();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IServiceProvider serviceProvider)
{
app.UseIdentity();
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});
// Adds IdentityServer
app.UseIdentityServer();
}
正如我已经提到的,它适用于没有负载平衡器的配置,但客户端因错误而失败
"Message contains error: 'invalid_request', error_description: 'error_description is null', error_uri: 'error_uri is null'."
在服务器端我收到
信息:IdentityServer4.Hosting.IdentityServerMiddleware[0]
调用 IdentityServer 端点:IdentityServer4.Endpoints.TokenEndpoint for /connect/token
警告:IdentityServer4.Endpoints.TokenEndpoint[0]
令牌端点的 HTTP 请求无效
我已经解决了问题。
找到解决方案跟踪 Request.HttpContext.Connection.RemoteIpAddress
它是无效的,等于负载均衡器的 IP。所以解决方案是使用以下方式添加 Ip:
options.KnownProxies.Clear();
options.KnownProxies.Add(IPAddress.Parse("LoadBalancer IP"));
app.UseForwardedHeaders(options);
或通过掩码,例如192.168.1.0/8:
options.KnownNetworks.Clear();
options.KnownNetworks.Add(new IPNetwork(IPAddress.Parse("192.168.1.0"), 8));
app.UseForwardedHeaders(options);
在这种情况下,客户端的 IP 将被传递到身份服务器,您不会收到异常:
Invalid HTTP request for token endpoint
负载均衡器后面的 IdentityServer 有问题,
需要说明的是,如果我使用的是直接 ip,一切都会按预期工作。
目前我在 LB 上有一个 SSL 配置,它带有一个有效的证书,可以重定向到 2 Linux 台机器上托管的 HTTP docker 引擎。
我在我的客户端上使用 MVC 混合流:
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
AuthenticationScheme = "oidc",
SignInScheme = "Cookies",
Authority = settings.Server,
RequireHttpsMetadata = "false",
ClientId = "MyMvcClient",
ClientSecret = "MyMvcSuperPassword",
ResponseType = "code id_token",
GetClaimsFromUserInfoEndpoint = true,
SaveTokens = true,
TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = JwtClaimTypes.Name,
RoleClaimType = JwtClaimTypes.Role,
},
Events = new OpenIdConnectEvents()
{
OnRemoteFailure = context =>
{
context.Response.Redirect("/error");
context.HandleResponse();
return Task.FromResult(0);
}
},
"Scope": { "openid", "profile", "email", "myclient", "offline_access" }
});
在服务器端,我有以下设置:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<IdentityDbContext>(builder);
services.AddIdentity<ApplicationUser, ApplicationRole>()
.AddEntityFrameworkStores<IdentityDbContext, Guid>()
.AddUserStore<UserStore<ApplicationUser, ApplicationRole, IdentityDbContext, Guid>>()
.AddRoleStore<RoleStore<ApplicationRole, IdentityDbContext, Guid>>()
.AddUserManager<LdapUserManager>()
.AddSignInManager<LdapSignInManager>()
.AddDefaultTokenProviders()
.AddIdentityServerUserClaimsPrincipalFactory();
...
string redisSettings = $"{redisHost}:{redisPort},ssl={redisSsl},abortConnect={redisAbortConnect},password={redisPassword}";
services.AddDataProtection().PersistKeysToRedis(redis, redisKey);
...
// Adds IdentityServer
services.AddIdentityServer()
.AddSigningCredential(new X509Certificate2("IdentityServerAuth.pfx"))
.AddConfigurationStore(builder)
.AddOperationalStore(builder)
.AddAspNetIdentity<ApplicationUser>()
.AddProfileService<IdentityProfileService>();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IServiceProvider serviceProvider)
{
app.UseIdentity();
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});
// Adds IdentityServer
app.UseIdentityServer();
}
正如我已经提到的,它适用于没有负载平衡器的配置,但客户端因错误而失败 "Message contains error: 'invalid_request', error_description: 'error_description is null', error_uri: 'error_uri is null'."
在服务器端我收到 信息:IdentityServer4.Hosting.IdentityServerMiddleware[0] 调用 IdentityServer 端点:IdentityServer4.Endpoints.TokenEndpoint for /connect/token 警告:IdentityServer4.Endpoints.TokenEndpoint[0] 令牌端点的 HTTP 请求无效
我已经解决了问题。 找到解决方案跟踪 Request.HttpContext.Connection.RemoteIpAddress 它是无效的,等于负载均衡器的 IP。所以解决方案是使用以下方式添加 Ip:
options.KnownProxies.Clear();
options.KnownProxies.Add(IPAddress.Parse("LoadBalancer IP"));
app.UseForwardedHeaders(options);
或通过掩码,例如192.168.1.0/8:
options.KnownNetworks.Clear();
options.KnownNetworks.Add(new IPNetwork(IPAddress.Parse("192.168.1.0"), 8));
app.UseForwardedHeaders(options);
在这种情况下,客户端的 IP 将被传递到身份服务器,您不会收到异常:
Invalid HTTP request for token endpoint