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

时间:2019-01-16 17:10:26

标签: 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此处给出的解决方案,但该方法也不起作用。

2 个答案:

答案 0 :(得分:1)

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

我正在使用Asp.Net Core 2.2,并且在帐户控制器中具有以下Logout()方法。我使用身份服务,然后选择退出而不是HttpContext。对我来说,此解决方案有效并删除了登录Cookie-至少在几分钟前我检查时已完成。

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

如果愿意,可以尝试一下,然后看看会得到什么。确保在startup.cs ConfigureServices方法中调用AddIdentity()或其变体。

enter image description here

答案 1 :(得分:1)

对于当前代码,您将MVC ControllerRazor Page合并在同一项目中,但是没有为MVC Controller配置任何路由。

首先,检查Logout表单的生成的html,确保其生成如下:

<form method="post" id="logoutForm" action="/Logout/Logout">
    <button type="submit">Logout</button>
<input name="__RequestVerificationToken" type="hidden" value="xxx"></form>

如果没有,请像

那样配置您的mvc路由
app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "default",
        template: "{controller=Home}/{action=Index}/{id?}");
});

这是一个正在运行的演示TestCookiesAuth