Cookie 身份验证失败 ASP.NET Core 3.1

时间:2021-03-23 09:19:33

标签: c# visual-studio google-chrome asp.net-core iis-express

我没有将现有的 ASP.NET Core 2.1 项目迁移到 3.1,而是创建了一个新项目。在新项目中,SignIn(...) 控制器方法执行没有错误,但随后无法重定向到指定的操作。相反,它重定向到 AccessDeniedPath

我的环境是使用 Chrome 的 Win10 VS 2019 IIS Express。

谁能告诉我是什么原因造成的?我在 3.1 中有什么遗漏或做错了吗?

PROGRAM.CS

public static void Main(string[] args)
{
    CreateHostBuilder(args).Build().Run();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
            //webBuilder.UseIISIntegration();
            //webBuilder.UseKestrel();
            //webBuilder.CaptureStartupErrors(true);
            //webBuilder.UseEnvironment(Environments.Development);
        });

STARTUP.CS

    public void ConfigureServices(IServiceCollection services)
    {
        try
        {
            services.AddRazorPages()        
                .AddRazorRuntimeCompilation();

            services.AddControllersWithViews();

            services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
                .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
                {
                    options.ExpireTimeSpan = new TimeSpan(30, 0, 0, 0);
                    options.LoginPath = new PathString("/Home/Index/");
                    options.AccessDeniedPath = new PathString("/Home/Index/");
                    options.LogoutPath = new PathString("/Home/Index/");
                    options.Validate();
                });

            services.Configure<Microsoft.AspNetCore.Identity.IdentityOptions>(options =>
            {
                options.Password.RequireDigit = true;
                options.Password.RequireLowercase = true;
                options.Password.RequireNonAlphanumeric = true;
                options.Password.RequireUppercase = true;
                options.Password.RequiredLength = 8;
                options.Password.RequiredUniqueChars = 1;
                options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
                options.Lockout.MaxFailedAccessAttempts = 5;
                options.Lockout.AllowedForNewUsers = true;
                options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
            });

            services.AddDetectionCore()
                .AddDevice();

            services.AddMvc();
            services.AddAntiforgery();
            services.Configure<MvcOptions>(options =>
            {
                options.Filters.Add(new RequireHttpsAttribute());
            });
        }
        catch (Exception ex)
        {
            gFunc.ProcessError(ex);
        }
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        try
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                app.UseHsts();
            }
            app.UseStaticFiles();
            app.UseHttpsRedirection();
            app.UseRouting();
            app.UseAuthorization();
            app.UseAuthentication();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });
        }
        catch (Exception ex)
        {
            gFunc.ProcessError(ex);
        }
    }

CONTROLLER.CS

    [HttpPost()]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> SignIn(SignIn sin)
    {
        bool is_err = false;
        try
        {
            // check data
            if (string.IsNullOrEmpty(sin.EmailAddress))
            {
                is_err = true;
                ModelState.AddModelError("Samadhi", "Missing email address.");
            }
            if (string.IsNullOrEmpty(sin.Password))
            {
                is_err = true;
                ModelState.AddModelError("Samadhi", "Missing password.");
            }

            // check authorisation
            if (ModelState.IsValid && !is_err)
            {
                sin = await RepoSamadhi.ShopSignIn(sin);
                if (sin.ShopID == 0 || sin.IsValidationFail || string.IsNullOrEmpty(sin.ShopToken))
                {
                    is_err = true;
                    ModelState.AddModelError("Samadhi", "Account not found. Check your credentials.");
                }
            }

            // check model state
            if (!ModelState.IsValid || is_err)
            {
                sin.IsSignInFailed = true;
                return View("SignIn", sin);
            }

            // create claims
            var claims = new List<Claim>
        {
            new Claim(ClaimTypes.Sid, sin.ShopToken),
            new Claim(ClaimTypes.NameIdentifier, sin.ShopID.ToString()),
            new Claim(ClaimTypes.Email, sin.EmailAddress.ToLower()),
            new Claim(ClaimTypes.Role, "SamadhiShop")
        };

            // create identity
            var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); 

            // create principal
            ClaimsPrincipal principal = new ClaimsPrincipal(new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme));

            var authProperties = new AuthenticationProperties
            {
                IsPersistent = true // sin.RememberMe
            };

            // sign-in
            await HttpContext.SignInAsync(scheme: CookieAuthenticationDefaults.AuthenticationScheme, principal: principal, properties: authProperties);
        }
        catch (Exception ex)
        {
            gFunc.ProcessError(ex);
        }
        return RedirectToAction("Console", new { date = DateTime.Today.ToString("d MMM yyyy"), timer = false });
    }

    [HttpGet]
    [Authorize]
    public async Task<ActionResult> Console(string date, bool timer)
    {
        int shop_id = int.Parse(User.FindFirst(ClaimTypes.NameIdentifier).Value);
        string token = User.FindFirst(ClaimTypes.Sid).Value;

        DateTime dt = DateTime.Parse(date);
        Shop ss = await RepoSamadhi.GetShop(shop_id, token, dt);
        ss.IsTimerOn = timer;
        return View((_device.Type == DeviceType.Mobile) ? "ConsoleM" : "ConsoleM", ss);
    }

1 个答案:

答案 0 :(得分:1)

你中间件的顺序不对,正确的应该是

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