ASP.NET Core 2.2-当浏览器(IE11和Edge)禁用cookie时,是否可以使用cookie身份验证?

时间:2019-03-26 22:57:22

标签: c# asp.net-core cookies asp.net-core-2.2

我发现我可以,所以必须对cookie感到困惑。

**********设置部分**********

我已完成以下操作:

  1. Visual Studio 2017:文件->新项目-> ASP.NET Core Web应用程序-> Web应用程序(模型-视图-控制器)。所有默认值(因此,“无身份验证”和“配置HTTPS”为true)。解决方案资源管理器将如下所示:

enter image description here

  1. 在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);
            });
    }
    
  2. 在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?}");
        });
    }
    
  3. 在为您创建的HomeController.cs的类中,我添加了[Authorize]标签:

        [Authorize]
        public class HomeController : Controller
        {
    
  4. 我在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; }
        }
    }
    
  5. 我创建了一个名为Data的新文件夹,并添加了一个名为ApplicationUser.cs的新类文件:

    namespace WebApplication1.Data
    {
        public class ApplicationUser
        {
            public string Email { get; set; }
            public string FullName { get; set; }
        }
    }
    
  6. 我在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");
            }
        }
    }
    
  7. 我在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>
    
  8. 这是我的cookie浏览器设置(IE11):

enter image description here

**********这是运行我的应用程序时的外观************

基于我的设置,当我运行该应用程序时,它将带我到登录页面,直到我登录后才能进入任何“主页”或“隐私视图”。这可行。这不是问题。

我想看看禁用浏览器中的cookie会发生什么。我知道我正确禁用了cookie,因为如果尝试登录到Facebook,我会收到消息“需要cookie”。但是,我可以按照自己的喜好运行我的小型测试应用程序,它将登录我,在20秒后过期(这将迫使我在单击链接后重新登录),等等。功能没有损失,它可以正常工作。

  1. 当我在禁用Cookie的情况下首次运行该应用程序时:

enter image description here

  1. 然后,我使用so@test.com用户登录(输入任何密码):

enter image description here

...而且我可以导航至所需的任何视图。

那么我在这里想念什么? Cookie身份验证的含义是否不同于与您的浏览器关联的Cookie?还是这是某种类型的服务器Cookie(相对于客户端Cookie或其他)?还是ASP.NET Core会以某种方式找出解决方法?

**********新信息**********

好像我应该尝试过IE以外的其他浏览器。 Firefox和Chrome达到了预期的效果,而IE和Edge忽略了我阻止其cookie的事实。有人知道为什么吗?对于其他浏览器没有/没有的Microsoft浏览器,这是否有特殊的魔力?

0 个答案:

没有答案