c# - HttpContext.SignOutAsync() 既不注销用户也不删除本地 cookie

标签 c# asp.net razor asp.net-core asp.net-core-2.2

我知道已经有关于此主题的问题,但给出的答案都不适用于我的情况。

这是核心:

Startup.cs

public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<comedyContext>(options =>
            options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

        services.Configure<CookiePolicyOptions>(options =>
        {
            // This lambda determines whether user consent for non-essential cookies is needed for a given request.
            options.CheckConsentNeeded = context => true;
            options.MinimumSameSitePolicy = SameSiteMode.None;
        });

        services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
            .AddCookie(options => {
                options.LoginPath = "/login/";
            });

        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseCookiePolicy();
        app.UseAuthentication();

        app.UseMvc();
    }

Login.cshtml.cs

    public class LoginModel : PageModel
{
    [BindProperty]
    public string inputUsername { get; set; }
    [BindProperty]
    public string inputPassword { get; set; }

    private readonly comedyContext _context;

    public LoginModel(comedyContext context)
    {
        _context = context;
    }

    public async Task<IActionResult> OnPostAsync()
    {
        var user = await _context.User.FirstOrDefaultAsync(u =>
            string.Equals(u.Username, inputUsername, StringComparison.CurrentCultureIgnoreCase) && string.Equals(u.Password, Utility.sha256_hash(inputPassword), StringComparison.CurrentCultureIgnoreCase));

        if (user is null)
            return Redirect("/login");

        var claims = new List<Claim>
        {
            new Claim(ClaimTypes.NameIdentifier, user.UserId.ToString()),
            new Claim(ClaimTypes.Name, inputUsername)
        };

        var userIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);

        var authProperties = new AuthenticationProperties
        {
            AllowRefresh = true,
            // Refreshing the authentication session should be allowed.

            ExpiresUtc = DateTimeOffset.UtcNow.AddHours(24),
            // The time at which the authentication ticket expires. A 
            // value set here overrides the ExpireTimeSpan option of 
            // CookieAuthenticationOptions set with AddCookie.

            IsPersistent = true,
            // Whether the authentication session is persisted across 
            // multiple requests. Required when setting the 
            // ExpireTimeSpan option of CookieAuthenticationOptions 
            // set with AddCookie. Also required when setting 
            // ExpiresUtc.

            IssuedUtc = DateTimeOffset.UtcNow,
            // The time at which the authentication ticket was issued.

            //RedirectUri = <string>
            // The full path or absolute URI to be used as an http 
            // redirect response value.
        };

        await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(userIdentity), authProperties);

        //Just redirect to our index after logging in. 
        return Redirect("/dashboard");
    }

    public void OnGet()
    {
    }
}

Dashboard.cshtml

@page
@using System.Security.Claims
@using Microsoft.AspNetCore.Identity
@using ComedyWebsite.Controllers
@model ComedyWebsite.Pages.DashboardModel
@{
}

Hello @User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Name)?.Value

<form asp-controller="Logout" asp-action="Logout" method="post" 
id="logoutForm">
    <button type="submit">Logout</button>
</form>

LogoutController.cs

public class LogoutController : Controller
{
    [HttpPost]
    public async Task<IActionResult> Logout()
    {
        // SomeOtherPage is where we redirect to after signout
        await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
        HttpContext.Response.Cookies.Delete($".AspNetCore.{CookieAuthenticationDefaults.AuthenticationScheme}");
        return Redirect("/");
    }
}


如下图所示,在点击注销按钮后,cookie 仍然存在于用户的浏览器中 proof

我尝试了 https://stackoverflow.com/questions/46131517/asp-net-core-identity-2-0-signoutasync 上给出的解决方案,但这也不起作用。

最佳答案

不完全是您的要求,但也许这种方法会有所帮助。

我正在使用 Asp.Net Core 2.2 并在帐户 Controller 中使用以下 Logout() 方法。我使用 Identity 服务并选择注销而不是 HttpContext。对我来说,这个解决方案有效并删除了登录 cookie——至少我几分钟前检查它时是这样。

它与您的代码的不同之处在于我使用的是 signInManager 对象而不是 HttpContext 对象,并且此 SignOutAsync() 不采用任何参数。

如果你愿意,试试看,看看你会得到什么。请务必在 startup.cs ConfigureServices 方法中调用 AddIdentity() 或其变体。

enter image description here

关于c# - HttpContext.SignOutAsync() 既不注销用户也不删除本地 cookie,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54222069/

相关文章:

html - 为什么我在 asp.net 中丢失了 CSS?

php - 说服 IT 经理允许使用 SQL Server 而不是 Access

asp.net-mvc - ASP MVC Ajax 和模型重新绑定(bind)

c# - WebClient() 可以同时下载多个字符串吗?

C# 动态引用集合对象?

c# - 计算方法的执行时间

asp.net-mvc - Visual Studio 2013 无法打开 Razor View - 'The operation could not be completed'

c# - F# 列表到 C# IEnumerable : most efficient method?

ASP.net 不为某些用户代理生成 javascript

asp.net - 如何在 Razor 中有条件地渲染表单?