IdentityServer4 给出堆栈溢出错误
Posted
技术标签:
【中文标题】IdentityServer4 给出堆栈溢出错误【英文标题】:IdentityServer4 gives stack overflow error 【发布时间】:2021-12-14 23:19:01 【问题描述】:我有一个 SPA (Angular 9) 并使用一个身份站点(.NET Core 3.1 和 identity4)。两个站点都运行良好,但是如果用户长时间停止浏览并尝试再次导航,身份站点会给出 503 错误(堆栈溢出错误)。
这是我在 Angular 9 上的配置,angular-oauth2-oidc。
// app.component.ts
// ----------------------------
export const authConfig: AuthConfig =
issuer: environment.authority,
redirectUri: environment.redirectUrl,
clientId: environment.clientId,
scope: "openid profile offline_access",
disablePKCE: false,
responseType: "code",
requireHttps: false,
logoutUrl: environment.authority + "/Account/Logout"
@Component(
selector: 'app-root',
templateUrl: './app.component.html'
)
export class AppComponent implements OnInit
title = 'app';
public isAuthenticated: Observable<boolean>;
public configs = null;
constructor(
private ouathService: OAuthService,
private storage: SessionStorageService
)
this.ouathService.configure(authConfig);
this.ouathService.tokenValidationHandler = new JwksValidationHandler();
// Authguard.js
// ----------------------------
export class AuthGuard implements CanActivate
constructor(..)
canActivate(..): boolean
if (this.oauthService.hasValidAccessToken())
console.log("Token validado");
let token = this.oauthService.getAccessToken();
//...
return true;
else
console.log("Inicia flujo");
this.oauthService.initImplicitFlow();
this.oauthService.loadDiscoveryDocumentAndTryLogin();
app.module.ts
----------------------------
@NgModule(
declarations: [..],
imports: [
//..
OAuthModule.forRoot(),
RouterModule.forRoot([
path: '', component: StartComponent ,
path: 'logout', component: LoginComponent ,
path: 'home', component: HomeComponent, canActivate: [AuthGuard, AppGuard] ,
])
],
providers: [
LoaderService,
provide: HTTP_INTERCEPTORS, useClass: TokenInterceptor, multi: true
],
bootstrap: [AppComponent]
)
这是我在 Identity 站点上的配置:.NET Core 3.1 和 identity4。
// Config
// ----------------------------
public IEnumerable<IdentityResource> GetIdentityResources()
return new List<IdentityResource>
new IdentityResources.OpenId(),
new IdentityResources.Profile()
;
public IEnumerable<Client> GetClients()
var client = _conf["URL_fronted"];
return new[]
new Client
ClientId = "..",
ClientName = "..",
AllowedGrantTypes = GrantTypes.Code,
RequireClientSecret = false,
RequirePkce = true,
RedirectUris = $"client" ,
FrontChannelLogoutUri = $"client",
PostLogoutRedirectUris = $"client/logout" ,
AllowOfflineAccess = true,
AllowedScopes = "openid","profile", "offline_access" ,
;
// Startup
// ----------------------------
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.Configure<IISServerOptions>(iis =>
iis.AuthenticationDisplayName = "Windows";
iis.AutomaticAuthentication = true;
);
var confIdentity = new ConfigIdentity(Configuration);
var builder = services.AddIdentityServer(options =>
options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseSuccessEvents = true;
)
.AddInMemoryIdentityResources(confIdentity.GetIdentityResources())
.AddInMemoryClients(confIdentity.GetClients())
.AddProfileService<IdentityWithAdditionalClaimsProfileService>();
builder.AddDeveloperSigningCredential();
services.AddCors(options =>
options.AddPolicy("CorsPolicy",
builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());
);
// IdentityWithAdditionalClaimsProfileService
// -----------------------------------------------
public class IdentityWithAdditionalClaimsProfileService : IProfileService
private readonly IUserClaimsPrincipalFactory<ApplicationUser> _claimsFactory;
private readonly UserManager<ApplicationUser> _userManager;
private ILogger<IdentityWithAdditionalClaimsProfileService> _logger;
private ApplicationDbContext _ctx;
public IdentityWithAdditionalClaimsProfileService(UserManager<ApplicationUser> userManager,
IUserClaimsPrincipalFactory<ApplicationUser> claimsFactory,
ILogger<IdentityWithAdditionalClaimsProfileService> logger,
ApplicationDbContext context)
_userManager = userManager;
_claimsFactory = claimsFactory;
_logger = logger;
_ctx = context;
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
var sub = context.Subject.GetSubjectId();
var user = _ctx.users.Where(..).FirstOrDefault();
if (user == null)
throw new Exception("No se encontro usuario para perfilar");
var claims = new List<Claim>();
claims.Add(new Claim(ClaimTypes.Name, user.Names));
claims.Add(new Claim(ClaimTypes.Email, user.Email));
if (user.RoleId != null)
var rolGlobal = _ctx.roles.Where(..).FirstOrDefault();
if (rolGlobal != null)
claims.Add(new Claim(ClaimTypes.Role, rolGlobal.AzureGroup));
context.IssuedClaims = claims;
public async Task IsActiveAsync(IsActiveContext context)
context.IsActive = true;
这是日志:
20:41:12 Debug] IdentityServer4.Hosting.EndpointRouter
Request path /.well-known/openid-configuration/jwks matched to endpoint type Discovery
[20:41:12 Debug] IdentityServer4.Hosting.EndpointRouter
Endpoint enabled: Discovery, successfully created handler: IdentityServer4.Endpoints.DiscoveryKeyEndpoint
[20:41:12 Information] IdentityServer4.Hosting.IdentityServerMiddleware
Invoking IdentityServer endpoint: IdentityServer4.Endpoints.DiscoveryKeyEndpoint for /.well-known/openid-configuration/jwks
[20:41:12 Debug] IdentityServer4.Endpoints.DiscoveryKeyEndpoint
Start key discovery request
[21:31:23 Debug] IdentityServer4.Hosting.CorsPolicyProvider
CORS request made for path: /.well-known/openid-configuration from origin: http://localhost:4200
[21:31:23 Debug] IdentityServer4.Services.InMemoryCorsPolicyService
Client list checked and origin: http://localhost:4200 is not allowed
[21:31:23 Warning] IdentityServer4.Hosting.CorsPolicyProvider
CorsPolicyService did not allow origin: http://localhost:4200
[21:31:23 Debug] IdentityServer4.Hosting.EndpointRouter
Request path /.well-known/openid-configuration matched to endpoint type Discovery
[21:31:23 Debug] IdentityServer4.Hosting.EndpointRouter
Endpoint enabled: Discovery, successfully created handler: IdentityServer4.Endpoints.DiscoveryEndpoint
[21:31:23 Information] IdentityServer4.Hosting.IdentityServerMiddleware
Invoking IdentityServer endpoint: IdentityServer4.Endpoints.DiscoveryEndpoint for /.well-known/openid-configuration
[21:31:23 Debug] IdentityServer4.Endpoints.DiscoveryEndpoint
Start discovery request
[21:31:23 Debug] IdentityServer4.Hosting.CorsPolicyProvider
CORS request made for path: /.well-known/openid-configuration/jwks from origin: http://localhost:4200
[21:31:23 Debug] IdentityServer4.Services.InMemoryCorsPolicyService
Client list checked and origin: http://localhost:4200 is not allowed
[21:31:23 Warning] IdentityServer4.Hosting.CorsPolicyProvider
CorsPolicyService did not allow origin: http://localhost:4200
[21:31:23 Debug] IdentityServer4.Hosting.EndpointRouter
Request path /.well-known/openid-configuration/jwks matched to endpoint type Discovery
[21:31:23 Debug] IdentityServer4.Hosting.EndpointRouter
Endpoint enabled: Discovery, successfully created handler: IdentityServer4.Endpoints.DiscoveryKeyEndpoint
[21:31:23 Information] IdentityServer4.Hosting.IdentityServerMiddleware
Invoking IdentityServer endpoint: IdentityServer4.Endpoints.DiscoveryKeyEndpoint for /.well-known/openid-configuration/jwks
[21:31:23 Debug] IdentityServer4.Endpoints.DiscoveryKeyEndpoint
Start key discovery request
Stack overflow.
【问题讨论】:
您在身份验证服务或警卫的某处进行了循环调用 能否在问题中包含IdentityWithAdditionalClaimsProfileService
类的源代码?
@AndrewSilver 我包含了代码 IdentityWithAdditionalClaimsProfileService。 SPA 站点,验证令牌,但如何过期,尝试更新并重定向到身份站点以进行新登录,但站点出现故障。
A 503 表示“服务不可用”,通常是暂时的。原因很可能是堆栈溢出异常,无论如何这将是您的 csharp 代码中的错误,而不是您的前端。另外,据我所知,罪魁祸首不在您在此处发布的代码中。我认为我们无法仅使用您发布的内容来重现您的问题。 - 尝试创建一个最小的示例设置并在此处分享所有详细信息,如果可以的话?祝你好运!
【参考方案1】:
我的问题是将 Identityserver 设置为 InMemory:
Startup.cs
var builder = services.AddIdentityServer(options =>
//...
)
.AddInMemoryIdentityResources(confIdentity.GetIdentityResources())
.AddInMemoryClients(confIdentity.GetClients())
当用户长时间停止浏览时,此设置不起作用。一段时间后,身份站点丢失了客户端的令牌,当试图找到它时,它给出了一个 *** 错误
有两种解决方案:
1.- 将配置更改为use entity framework
services.AddIdentityServer()
// this adds the operational data from DB (codes, tokens, consents)
.AddOperationalStore(options =>
options.ConfigureDbContext = builder =>
builder.UseSqlServer(connectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
// this enables automatic token cleanup. this is optional.
options.EnableTokenCleanup = true;
options.TokenCleanupInterval = 3600; // interval in seconds (default is 3600)
);
2.- 客户端向refresh token发送请求
app.component.ts
this.ouathService.refreshToken();
【讨论】:
以上是关于IdentityServer4 给出堆栈溢出错误的主要内容,如果未能解决你的问题,请参考以下文章
有人可以指出代码“满足给定总和条件的子序列数”的错误,这会导致堆栈溢出错误