我使用 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。
有什么帮助吗?
根据你的代码,你使用的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);