.Net 8:无法使用“个人帐户身份验证”模板注销用户

问题描述 投票:0回答:1

我使用 MVC 的默认 .Net 模板(ASP.NET Core Web 应用程序)从头开始创建了一个 Web 应用程序,使用带有“个人帐户”选项的身份验证和 SDK 8,我的问题是我无法注销用户(我发现登录也很有问题,但最终解决了这个问题)。

Program.cs

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");

builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();

builder.Services.AddDefaultIdentity<IdentityUser>()
    .AddEntityFrameworkStores<ApplicationDbContext>();

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

builder.Services.AddControllersWithViews();
builder.Services.AddScoped<IAWSService, AWSService>();
builder.Services.AddScoped<IAWSRepo, AWSRepo>();
builder.Services
            .Configure<Settings>(builder.Configuration)
            .AddSingleton(sp => sp.GetRequiredService<IOptions<Settings>>().Value);

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseMigrationsEndPoint();
}
else
{
    app.UseExceptionHandler("/Home/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.UseRouting();

app.UseAuthorization();
app.UseAuthentication();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapRazorPages();

app.Run();

Login.cshtml.cs

public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
    returnUrl ??= Url.Content("~/");

    ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();

    if (ModelState.IsValid)
    {
        // This doesn't count login failures towards account lockout
        // To enable password failures to trigger account lockout, set lockoutOnFailure: true
        //var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: false);

        var result = SignInResult.Failed;
        var aws = new AWS_Manager(TestController.access_id, TestController.secret_key);

        UserModel oUser = await Task.Run(() => aws.getUser(Input.Email));
        if (oUser != null)
        {
            if (oUser.Password == Crypto.GetSHA1(Input.Password)) // && oUser.testloader_enabled == true)
            {
                //A claim is a statement about a subject by an issuer and    
                //represent attributes of the subject that are useful in the context of authentication and authorization operations.    
                var claims = new List<Claim>() {
                            // adding following 2 claim just for supporting default antiforgery provider
                            new Claim(ClaimTypes.NameIdentifier, Input.Email),
                            new Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider",
                            "ASP.NET Identity", "http://www.w3.org/2001/XMLSchema#string"),
                            new Claim(ClaimTypes.Name, Input.Email),

                            // optionally you could add roles if any
                            // new Claim(ClaimTypes.Role, "RoleName"),
                            // new Claim(ClaimTypes.Role, "AnotherRole"),
                };
                //Initialize a new instance of the ClaimsIdentity with the claims and authentication scheme    
                var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
                //Initialize a new instance of the ClaimsPrincipal with ClaimsIdentity    
                var principal = new ClaimsPrincipal(identity);
                //SignInAsync is a Extension method for Sign in a principal for the specified scheme.    
                await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal, new AuthenticationProperties()
                {
                    IsPersistent = Input.RememberMe
                });
                return LocalRedirect(returnUrl);
            }
        }

        if (result.RequiresTwoFactor)
        {
            return RedirectToPage("./LoginWith2fa", new { ReturnUrl = returnUrl, RememberMe = Input.RememberMe });
        }
        if (result.IsLockedOut)
        {
            _logger.LogWarning("User account locked out.");
            return RedirectToPage("./Lockout");
        }
        else
        {
            ModelState.AddModelError(string.Empty, "Invalid login attempt.");
            return Page();
        }
    }

    // If we got this far, something failed, redisplay form
    return Page();
}

_LoginPartial.cshtml

public class LogoutModel : PageModel
{
    private readonly SignInManager<IdentityUser> _signInManager;
    private readonly ILogger<LogoutModel> _logger;

    public LogoutModel(SignInManager<IdentityUser> signInManager, ILogger<LogoutModel> logger)
    {
        _signInManager = signInManager;
        _logger = logger;
    }

    public async Task<IActionResult> OnPost(string returnUrl = null)
    {
        await _signInManager.SignOutAsync();
        _logger.LogInformation("User logged out.");
        if (returnUrl != null)
        {
            return LocalRedirect(returnUrl);
        }
        else
        {
            // This needs to be a redirect so that the browser performs a new
            // request and the identity for the user gets updated.
            //return RedirectToPage();
            return LocalRedirect(returnUrl);
        }
    }
}

Logout.cshtml

@page
@model LogoutModel
@{
    ViewData["Title"] = "Log out";
}

<header>
    <h1>@ViewData["Title"]</h1>
    @{
        if (User.Identity?.IsAuthenticated ?? false)
        {
            <form class="form-inline" asp-area="Identity" asp-page="/Account/Logout" asp-route-returnUrl="@Url.Page("/", new { area = "" })" method="post">
                <button type="submit" class="nav-link btn btn-link text-dark">Click here to Logout</button>
            </form>
        }
        else
        {
            <p>You have successfully logged out of the application.</p>
        }
    }
</header>

Logout.cshtml.cs

public class LogoutModel : PageModel
{
    private readonly SignInManager<IdentityUser> _signInManager;
    private readonly ILogger<LogoutModel> _logger;

    public LogoutModel(SignInManager<IdentityUser> signInManager, ILogger<LogoutModel> logger)
    {
        _signInManager = signInManager;
        _logger = logger;
    }

    public async Task<IActionResult> OnPost(string returnUrl = null)
    {
        await _signInManager.SignOutAsync();
        _logger.LogInformation("User logged out.");
        if (returnUrl != null)
        {
            return LocalRedirect(returnUrl);
        }
        else
        {
            // This needs to be a redirect so that the browser performs a new
            // request and the identity for the user gets updated.
            //return RedirectToPage();
            return LocalRedirect(returnUrl);
        }
    }
}

我在 Logout.cshtml.cs 的 OnPost 中设置的断点被命中,但显然

await _signInManager.SignOutAsync();
不起作用,因为
User.Identity.IsAuthenticated
不断返回 true。

有什么帮助吗?

asp.net-mvc asp.net-core asp.net-identity logout claims-based-identity
1个回答
0
投票

根据你的代码,你使用的cookie认证实际上并不是你登录页面内的身份,所以你使用_signInManager不会注销cookie认证cookie。

在 Login.cshtml.cs 中,使用以下代码:

            await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal, new AuthenticationProperties()
            {
                IsPersistent = Input.RememberMe
            });

因此,如果您想注销用户,您应该使用以下代码而不是

_signInManager.SignOutAsync()

// Clear the existing external cookie
await HttpContext.SignOutAsync(
    CookieAuthenticationDefaults.AuthenticationScheme);
© www.soinside.com 2019 - 2024. All rights reserved.