ASP.NET Core中未经授权时重定向到登录页面

58

在以前的ASP.NET MVC中,有一个选项可以重定向到登录操作,如果用户未经过身份验证。

我需要在ASP.NET Core中做同样的事情,因此我:

  1. 从Visual Studio模板创建了一个ASP.NET Core项目
  2. [Authorize]添加到某个任意操作
  3. 在浏览器中打开相应的视图

我不希望重定向,因为我还没有进行配置。但是,它自动重定向到登录操作!

这个选项在哪里/如何设置?


2
该框架能够找到登录操作,因为它使用约定优于配置的方式。 - sudheeshix
14
如果这没有任何记录,那么这就是一种魔法。即使有记录,现在也有太多这样的事情发生了,特别是在 ASP.NET 中。 - grokky
别担心,在下一个版本的Core中,这一切都会改变。然后在下一个版本中再次改变,以此类推... - Steve Smith
9个回答

38

随着当前的aspnet core版本(2.1.0),这已经改变了,现在你可以使用扩展:

使用当前的aspnet核心版本(2.1.0), 这种情况已经改变,现在您可以使用扩展功能:

   services.ConfigureApplicationCookie(options => options.LoginPath = "/login");
或者
 services
         .AddAuthentication()
         .AddCookie(options =>
         {
             options.LoginPath = "/login";
             options.LogoutPath = "/logout";
         });

您可以在此文章中了解有关迁移到 2.0 的更多信息。


4
我想补充一点,ConfigureApplicationCookie 应该放在 AddIdentity 之后。否则它就没有作用。 - Igor Mikushkin

23

我的应用程序中重定向根本不起作用,这里的任何解决方案都没有解决它,但使用状态代码页就可以解决:

app.UseStatusCodePages(async context => 
{
    var response = context.HttpContext.Response;

    if (response.StatusCode == (int)HttpStatusCode.Unauthorized ||
            response.StatusCode == (int)HttpStatusCode.Forbidden)
        response.Redirect("/Authentication");
});

app.UseMvc(...        

你把它放在管道调用栈的哪个位置了? - c_Reg_c_Lark
4
app.UseMvc之前,应该是第一个或其中之一。 - Serj Sagan
当我将ASP.NET Core 6应用程序托管在IIS Web服务器上时,这似乎对我不起作用。会话过期后,服务器仍然只会向客户端返回401未经授权的状态码,而不是将用户重定向到登录页面。我找到的所有其他解决方案(ConfigureApplicationCookie、AddCookie等)也都没有起作用。 - Chris
@Chris 你可能需要将它在你的服务注册栈中提高。 - Serj Sagan

13

您可以使用CookieAuthenticationOptions类配置路径。

类似这样。

app.UseCookieAuthentication(new CookieAuthenticationOptions {
        LoginPath = new PathString("/Login/"),
        AuthenticationType = "My-Magical-Authentication",
        // etc...
        },
});

这里是更新后的链接,用于CookieAuthenticationHandler


我在这篇文章中看到了这个内容(https://docs.asp.net/en/latest/security/authentication/cookie.html),但是那里说“在没有使用ASP.NET Core Identity的情况下使用Cookie中间件”。而我正在使用Identity。 - grokky
7
除了希望控制这个设置外,我还想了解它是在哪里/如何发生的。我不明白它如何知道找到我的登录视图。这就是我想要理解的内容。 - grokky
1
请查看此代码 - https://github.com/aspnet/Security/blob/dev/src/Microsoft.AspNetCore.Authentication.Cookies/CookieAuthenticationHandler.cs#L379 - Anuraj
2
@Anuraj 的链接已经失效了,你知道新的链接吗? - Alexander
@Alexander 已更新链接 - https://github.com/dotnet/aspnetcore/blob/main/src/Security/Authentication/Cookies/src/CookieAuthenticationHandler.cs - Anuraj

6

这个启动文件中的代码块对于我在 .Net Core 3.1 上运行有效。

services.ConfigureApplicationCookie(options =>
    {
        // Cookie settings
        options.Cookie.HttpOnly = true;
        options.ExpireTimeSpan = TimeSpan.FromMinutes(5);

        options.LoginPath = "/Identity/Account/Login";
        options.AccessDeniedPath = "/Identity/Account/AccessDenied";
        options.SlidingExpiration = true;
    });


1
我已经添加了这个,但是没有改变任何东西,它仍然重定向到/Account。 - Steve Smith

6

对于任何感兴趣的人,也可以使用AddIdentity服务提供程序来完成此操作。

services.AddIdentity<User, IdentityRole>(options =>
    {
        options.Cookies.ApplicationCookie.AutomaticAuthenticate = true;
        options.Cookies.ApplicationCookie.AutomaticChallenge = true;
        options.Cookies.ApplicationCookie.LoginPath = "/Auth/Login";
    })
    .AddEntityFrameworkStores<MehandiContext>()
    .AddDefaultTokenProviders();

如此解释:https://dev59.com/8p3ha4cB1Zd3GeqPatk1#41643105

我在2017年4月尝试过,但"Microsoft.AspNetCore.Identity.EntityFrameworkCore": "1.1.0"无法重定向,必须使用1.0.1版本。


在我使用的版本1.1.0(2017年7月)中运行良好。 - Wouter
Anton / @Wouter,你们在使用.NET Core 吗? - susieloo_
使用 .NET Core 1.1 - Wouter
在2.0及更高版本中:如果您想调整身份验证cookie,则它们不再是IdentityOptions的一部分。相反,我们必须使用ConfigureApplicationCookie方法。例如 services.ConfigureApplicationCookie(options => options.LoginPath = "/Account/LogIn");更多信息,请参见此处:https://learn.microsoft.com/en-us/aspnet/core/migration/1x-to-2x/identity-2x?view=aspnetcore-2.1 - Sayyed Dawood

5

dotnet core构建Cookie身份验证的方式是使用Identity框架。对于新项目,我建议打开命令行并执行以下操作:

dotnet new mvc -o ExampleProject --auth Individual

您可以通过修改Startup.cs中的以下方法来完全控制认证过程,使其如下所示:
public void ConfigureServices(IServiceCollection services)
{
    services.Configure<CookiePolicyOptions>(options =>
    {
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });

    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));

    services.AddIdentity<IdentityUser, IdentityRole>()
        // services.AddDefaultIdentity<IdentityUser>()
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
        .AddRazorPagesOptions(options =>
        {
            options.AllowAreas = true;
            options.Conventions.AuthorizeAreaFolder("Identity", "/Account/Manage");
            options.Conventions.AuthorizeAreaPage("Identity", "/Account/Logout");
        });

    services.ConfigureApplicationCookie(options =>
    {
        options.LoginPath = $"/Identity/Account/Login";
        options.LogoutPath = $"/Identity/Account/Logout";
        options.AccessDeniedPath = $"/Identity/Account/AccessDenied";
    });

    // using Microsoft.AspNetCore.Identity.UI.Services;
    services.AddSingleton<IEmailSender, EmailSender>();
}

参考: https://learn.microsoft.com/en-us/aspnet/core/security/authentication/scaffold-identity?view=aspnetcore-2.2&tabs=visual-studio#full 我的个人偏好是使用IdentityServer4的混合流程,这为您配置多个应用程序提供了一个范围,使用单个登录即可实现。

对我来说起到了作用。使用asp.net core 3.1 mvc项目,谢谢。 - conterio

1
在配置中间件管道时,放置应该是重要的。
app.UseSession();
        app.UseAuthentication();
        app.UseStatusCodePages(context => {
            var response = context.HttpContext.Response;
            if (response.StatusCode == (int)HttpStatusCode.Unauthorized ||
                response.StatusCode == (int)HttpStatusCode.Forbidden)
                response.Redirect("/Login");
            return Task.CompletedTask;
        });
        app.UseClaimsMiddleware();
        app.UseAuthorization();

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

0

上面的代码在使用asp net core 3.1中的身份验证时对我很有效。

  1. 首先,您必须将以下代码添加到Startup.cs文件中
services.ConfigureApplicationCookie(options =>
{
     options.Cookie.Name = ".AspNetCore.Identity.Application";
     options.AccessDeniedPath = "/User/PageNotAllowed";               
});
  1. 在您的控制器中创建一个操作,负责管理用户帐户(在我的情况下是User类)
public IActionResult PageNotAllowed()
{
    return View();
}

第三步,您只需要按照自己的喜好创建PageNotAllowed视图。

0
应用程序知道登录页面所在的原因是默认情况下,“登录”页面应该放置在“帐户”文件夹中,页面应该被称为“Login”,就像“Account/Login”一样。
因此,如果您将“帐户”文件夹更改为其他内容,例如“AccountFolder”,则会收到http 404页未找到的错误消息。
要明确指定登录页面的位置,请转到“Program.cs”文件,并添加以下“LoginPath”定义。
builder.Services.AddAuthentication().AddCookie("YourCookieName", options =>
{
    options.Cookie.Name = "YourCookieName";
    options.LoginPath = "/Account/Login";
});

以上示例来自.NET 6


你好,我已经完成了这个任务,但是出现了401错误页面 :-( - jstuardo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接