Я обнаружил, что могу, поэтому я должен быть смущен насчет файлов cookie.
********** РАЗДЕЛ НАСТРОЙКИ **********
Я сделал следующее:
- Visual Studio 2017: Файл -> Новый проект -> Базовое веб-приложение ASP.NET -> Веб-приложение (модель-представление-контроллер). Все значения по умолчанию (таким образом, Нет аутентификации, и Настройка для HTTPS отмечена как истинная). Обозреватель решений будет выглядеть так:
В Startup.cs я изменил ConfigureServices:
public void ConfigureServices(IServiceCollection services)
{
// THIS WAS COMMENTED OUT
//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.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
// THIS WAS ADDED
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = false;
options.ExpireTimeSpan = TimeSpan.FromSeconds(20);
});
}
В Startup.cs я изменил Configure:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
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();
// THIS WAS COMMENTED OUT
//app.UseCookiePolicy();
// THIS WAS ADDED
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
В классе для HomeController.cs, который создан для вас, я добавил тег [Authorize]:
[Authorize]
public class HomeController : Controller
{
Я добавил новый файл класса в папку Models с именем AccountModel.cs, вот как это выглядит:
namespace WebApplication1.Models
{
public class LoginViewModel
{
[Required]
[Display(Name = "Email")]
[EmailAddress]
public string Email { get; set; }
[Required]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[Display(Name = "Remember me?")]
public bool RememberMe { get; set; }
}
}
Я создал новую папку с именем Data и добавил новый файл класса с именем ApplicationUser.cs:
namespace WebApplication1.Data
{
public class ApplicationUser
{
public string Email { get; set; }
public string FullName { get; set; }
}
}
Я добавил новый файл класса в папку Controllers под названием AccountControleler.cs, вот как это выглядит:
namespace WebApplication1.Controllers
{
public class AccountController : Controller
{
public IActionResult Login()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginViewModel model, string returnUrl)
{
if (!ModelState.IsValid)
{
return View(model);
}
ApplicationUser appUser = await AuthenticateUser(model.Email, model.Password);
if (appUser == null)
{
ModelState.AddModelError("", "Invalid login attempt.");
return View(model);
}
List<Claim> claims = new List<Claim>
{
new Claim(ClaimTypes.Name, appUser.FullName),
new Claim("FullName", appUser.FullName),
new Claim(ClaimTypes.Email, appUser.Email),
new Claim(ClaimTypes.Role, "Administrator")
};
ClaimsIdentity claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
AuthenticationProperties authProperties = new AuthenticationProperties();
await HttpContext.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(claimsIdentity),
authProperties);
return RedirectToLocal(returnUrl);
}
private async Task<ApplicationUser> AuthenticateUser(string email, string password)
{
await Task.Delay(500);
if (email == "so@test.com")
{
return new ApplicationUser()
{
Email = "so@test.com",
FullName = "Stack Overflow"
};
}
else
{
return null;
}
}
private ActionResult RedirectToLocal(string returnUrl)
{
if (Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
return RedirectToAction("Index", "Home");
}
}
}
Я создал новую папку в папке Views с именем Account и добавил новый класс с именем Login.cshtml:
@model WebApplication1.Models.LoginViewModel
@{
ViewData["Title"] = "Login";
}
<h2 class="text-primary">@ViewBag.Title</h2>
<div class="row">
<div class="col-md-8">
<section id="loginForm">
@*https://dustinewers.com/how-to-build-html-helpers-like-html-beginform-in-asp-net-mvc/*@
@*https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.rendering.ihtmlhelper.beginform?view=aspnetcore-2.2*@
@*@Html.BeginForm("Login", "Account",TModel-routeValues,FormMethod.Post, bool?-AntiforgeryExtensions, TModel-htmlAttributes)*@
@using (Html.BeginForm("Login", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, null, new { @class = "form-horizontal", role = "form" }))
{
@Html.AntiForgeryToken()
<h4 class="text-primary">Use a local account to log in.</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.TextBoxFor(m => m.Email, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.Email, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.PasswordFor(m => m.Password, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.Password, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<div class="checkbox">
@Html.CheckBoxFor(m => m.RememberMe)
@Html.LabelFor(m => m.RememberMe)
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Log in" class="btn btn-default btn-primary" />
</div>
</div>
<p>
@Html.ActionLink("Register as a new user", "Register")
</p>
@* Enable this once you have account confirmation enabled for password reset functionality
<p>
@Html.ActionLink("Forgot your password?", "ForgotPassword")
</p>*@
}
</section>
</div>
</div>
Это мои настройки браузера (IE11) для файлов cookie:
********** ЗДЕСЬ, ЧТО ЭТО ВЫглядит, КАК когда я запускаю приложение **********
Исходя из того, что я настроил, при запуске приложения оно переместится на страницу входа в систему, и я не смогу перейти ни в один из домашних или конфиденциальных видов, пока не войду в систему. Это работает. Это не проблема.
Я хотел посмотреть, что произойдет, если я отключу куки в браузере. Я знаю, что правильно отключил файлы cookie, потому что, если я попытаюсь войти в Facebook, я получу сообщение «Требуются файлы cookie». Тем не менее, я могу запустить мое маленькое тестовое приложение для моего сердца, и оно войдет в систему, истечет через 20 секунд (что приведет к повторному входу в систему, как только я нажму на ссылку) и т. Д. Без потери функциональности, это работает.
- При первом запуске приложения с отключенными файлами cookie:
- Затем я вхожу в систему, используя моего пользователя so@test.com (введите любой пароль):
... И я могу перейти к любому желаемому виду.
Так чего мне здесь не хватает? Означает ли авторизация файлов cookie нечто иное, чем файлы cookie, связанные с вашим браузером? Или это какой-то тип файлов cookie сервера (против файла cookie клиента или чего-то еще)? Или ASP.NET Core каким-то образом решает эту проблему?
********** НОВАЯ ИНФОРМАЦИЯ **********
Похоже, я должен был попробовать другой браузер, кроме IE. Firefox и Chrome сделали как положено, тогда как IE и Edge игнорируют тот факт, что у меня заблокированы куки. Кто-нибудь знает почему? Это какая-то особая магия для браузеров Microsoft, которую другие браузеры не имеют / получают?