Я слежу за проектом IdentityServer4 Quickstart , чтобы узнать, как он реализован.Мой Startup.cs
почти идентичен, моя реализация класса AccountController.cs
более или менее одинакова и так далее.
Однако, похоже, существует какой-то низкоуровневый конфликт с обработкой файлов cookie локальной аутентификации.
1) При запуске я не вызываю app.UseAuthentication()
, поскольку IdentityServer устанавливает, чтопозже.Я дошел до того, что скопировал services.AddAuthentication()
из стенографического проекта быстрого запуска, но все еще возникают проблемы.
При входе в проект Quickstart создает два файла cookie: один файл cookie проверки фальсификации и один файл cookie с именемidsrv
.Нигде в проекте это явно не определено для этого.
Однако, когда я запускаю его реализацию, я получаю три файла cookie: файл cookie проверки фальсификации, файл cookie idsrv.session
и файл cookie .AspNetCore.Identity.Application
,Я могу заставить ASP.NET назвать файл cookie «idsrv», но наличие файла cookie .session заставляет меня поверить, что он не использует правильную схему.
2) Когда я пытаюсь выйти из системы с помощьюПри вызове HttpContext.SignOutAsync()
cookie не удаляется и ничего не происходит: он остается в системе. Я нашел вопросы с похожими проблемами, но, похоже, это: а) реализация внешней аутентификации и б) реализация перенаправлений, которые якобы перезаписывают URL-адрес выхода.Я ничего не делаю.
Моя реализация входа в систему:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login( LoginInputModel model, string action )
{
var context = await _interactionService.GetAuthorizationContextAsync( model.ReturnUrl );
if( action != "Login" )
{
if( context != null )
{
// Handle a cancelled login
await _interactionService.GrantConsentAsync( context, ConsentResponse.Denied );
}
else
return Redirect( "~/" );
}
var errors = ModelState.Values.SelectMany( v => v.Errors );
if( ModelState.IsValid )
{
var user = await _userManager.FindByNameAsync( model.Username );
if( user != null && await _userManager.CheckPasswordAsync( user, model.Password ) )
{
await _eventService.RaiseAsync( new UserLoginSuccessEvent( user.UserName, user.Id, user.UserName ) );
//Handle RememberMe Checkbox
AuthenticationProperties props = null;
if( model.RememberMe )
{
props = new AuthenticationProperties
{
IsPersistent = true,
ExpiresUtc = DateTimeOffset.UtcNow.Add( Config.AccountRememberMeDuration ),
};
}
//Issue Auth Cookie
await HttpContext.SignInAsync( user.Id, user.UserName, props );
if( _interactionService.IsValidReturnUrl( model.ReturnUrl ) || Url.IsLocalUrl( model.ReturnUrl ) )
return Redirect( model.ReturnUrl );
return Redirect( "~/" );
}
//If we made it this far, the authentication failed
await _eventService.RaiseAsync( new UserLoginFailureEvent( model.Username, "Invalid Credentials" ) );
ModelState.AddModelError( "", "Invalid Credentials" );
}
//Display form with error message
model.Password = string.Empty;
return View( model );
}
Моя реализация выхода из системы:
[HttpGet]
public async Task Logout( LogoutInputModel model )
{
if( User?.Identity.IsAuthenticated == true )
{
await HttpContext.SignOutAsync();
await _eventService.RaiseAsync( new UserLogoutSuccessEvent( User.GetSubjectId(), User.GetDisplayName() ) );
}
}
Мой запуск .cs:
public void ConfigureServices( IServiceCollection services )
{
services.AddMvc();
services.AddIdentityServer()
.AddOperationalStore( options =>
{
options.ConfigureDbContext = builder =>
builder.UseSqlServer( Config.ConnectionString, sqlOptions => sqlOptions.MigrationsAssembly( Config.MigrationsAssembly ) );
options.EnableTokenCleanup = true;
options.TokenCleanupInterval = 30; //Every 30 seconds
} )
.AddConfigurationStore( options =>
{
options.ConfigureDbContext = builder =>
builder.UseSqlServer( Config.ConnectionString, sqlOptions => sqlOptions.MigrationsAssembly( Config.MigrationsAssembly ) );
} )
.AddDeveloperSigningCredential();
services.AddDbContext<CustomUserContext>( builder =>
builder.UseSqlServer( Config.ConnectionString, sqlOptions => sqlOptions.MigrationsAssembly( Config.MigrationsAssembly ) )
);
services.AddIdentity<CustomUser, CustomRole>()
.AddEntityFrameworkStores<CustomUserContext>();
services.AddAuthentication();
}
public void Configure( IApplicationBuilder app, IHostingEnvironment env )
{
if( env.IsDevelopment() )
app.UseDeveloperExceptionPage();
app.UseIdentityServer();
app.UseStaticFiles();
app.UseMvcWithDefaultRoute(); //TODO: Routes
}
Как я вызываю функцию выхода из системы:
<div class="account-actions">
@using( Html.BeginForm( "Logout", "Account", FormMethod.Get ) )
{
<input type="submit"
class="account-action-button account-action-logout"
value="Logout" />
}
</div>