asp.net HttpContext.SignOutAsync()不删除本地cookie

zu0ti5jz  于 2023-10-21  发布在  .NET
关注(0)|答案(2)|浏览(135)

我正在沿着IdentityServer4 Quickstart project来了解它是如何实现的。我的Startup.cs几乎是相同的,我的AccountController.cs类的实现或多或少是相同的,等等。
然而,似乎有某种低级别的冲突与如何处理本地身份验证cookie。
1.在启动时,我没有调用app.UseAuthentication(),因为IdentityServer稍后会设置它。我已经从quickstart项目中逐字复制了services.AddAuthentication(),但仍然有问题。
登录时,Quickstart项目会生成两个cookie:一个防伪验证cookie和一个名为idsrv的cookie。项目中没有任何地方明确定义这样做。
然而,当我运行它的实现时,我得到了三个cookie:防伪验证cookie、idsrv.session cookie和.AspNetCore.Identity.Application cookie。我可以强制ASP.NET将cookie命名为“idsrv”,但.session cookie的存在使我相信它没有使用正确的方案。
1.当我尝试通过调用HttpContext.SignOutAsync()注销时,cookie没有被删除,什么也没有发生:它会保持登录状态我发现了类似的问题,但这些问题似乎是a)实现外部认证和b)实现重定向,据说覆盖了注销网址。我两样都不做。
我的登录实现:

[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() ) );
   }
}

My Startup.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

}

如何调用logout函数:

<div class="account-actions">
    @using( Html.BeginForm( "Logout", "Account", FormMethod.Get ) )
    {
        <input type="submit"
               class="account-action-button account-action-logout"
               value="Logout" />
    }
</div>
whlutmcx

whlutmcx1#

我也有同样的问题。我想我可能会尝试调用SignOutAsync( schema )代替。尝试注销一个不存在的模式时,我得到一条错误消息,其中包含受支持的模式列表。其中一个是“身份。应用程序”,并在上面做了一个签名。例如await this.HttpContext.SignOutAsync( "Identity.Application" );

uemypmqf

uemypmqf2#

据我所知,你在你的MVC应用程序中共同托管了IdentityServer,我相信你需要为 * 你的MVC应用程序 * 配置Cookie中间件。您现在在Startup.cs中的配置是针对IdentityServer本身的。你得到的cookie是身份服务器的cookie。
看看如何在此示例中配置cookie身份验证+ OIDC:https://github.com/IdentityServer/IdentityServer4.Samples/blob/release/Clients/src/MvcHybrid/Startup.cs

相关问题