登录成功后授权页面重定向回登录

gyu*_*isc 6 c# authentication asp.net-core-mvc .net-core asp.net-core

我有一个使用 2.1 版的简单 asp.net-core 应用程序。HomeController 有一个带有authorized 属性的页面。当我点击需要授权的关于页面时,我会进入登录页面,在输入我的用户名和密码后,会发生以下情况:

  • 用户已成功登录
  • 用户被重定向到 /Home/About
  • HomeController.About 方法在调试器中被命中,并提供了 About 视图。
  • 以某种方式用户被重定向回 AccountController.Login
  • 用户已登录,因此我现在可以导航到任何需要授权的页面。

我也用 Chrome 和 Edge 试过这个。我可以用两个浏览器重现错误。

我创建了一个小型 repro 项目,可以在我的机器和设置上重现该问题。

Portfolio_Authentication

我用来重现问题的步骤如下:

  1. 在网站上注册用户
  2. 如果用户已登录,则注销该用户。
  3. 单击标题中的“关于”菜单链接。
  4. 输入用户名和密码
  5. 请注意,身份验证是可以的,因为用户名可以在屏幕的右上角看到,但登录不会重定向到“关于”页面。

我想知道为什么会发生这种情况以及如何纠正这个问题?谢谢你帮助我。欢迎所有反馈。

家庭控制器:

public class HomeController : Controller
{
    public IActionResult Index()
    {
        return View();
    }

    [Authorize]
    public IActionResult About()
    {
        ViewData["Message"] = "Your application description page.";

        return View();
    } 
}
Run Code Online (Sandbox Code Playgroud)

我的 Startup.cs 如下所示:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

        services.AddIdentity<ApplicationUser, IdentityRole>()
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddDefaultTokenProviders();

        // services.AddAuthentication();
        services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
                .AddCookie(options =>
                {
                    options.LoginPath = "/Account/LogIn";
                    options.LogoutPath = "/Account/LogOff";
                });

        // Add application services.
        services.AddTransient<IEmailSender, EmailSender>();

        services.AddMvc()
                .AddFeatureFolders(); // .SetCompatibilityVersion(CompatibilityVersion.Version_2_1); ;
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseBrowserLink();
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
        }

        app.UseStaticFiles();

        app.UseAuthentication();

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我在 Visual Studio 的输出窗口中看到的日志:

public class HomeController : Controller
{
    public IActionResult Index()
    {
        return View();
    }

    [Authorize]
    public IActionResult About()
    {
        ViewData["Message"] = "Your application description page.";

        return View();
    } 
}
Run Code Online (Sandbox Code Playgroud)

Kir*_*kin 4

在您的 Github 项目中,您有一个site.js文件,其中包含(除其他外)以下 jQuery 事件处理程序:

$('form[method=post]').not('.no-ajax').on('submit', function () {
    ...

    $.ajax({
        url: $this.attr('action'),
        ...
        statusCode: {
            200: redirect
        },
        ...
    }).error(highlightErrors);

    return false;
}
Run Code Online (Sandbox Code Playgroud)

当您提交登录表单时,您最终会运行上面的这段代码,然后调用redirecta statusCodeof的回调函数200,如下所示:

var redirect = function (data) {
    if (data.redirect) {
        window.location = data.redirect;
    } else {
        window.scrollTo(0, 0);
        window.location.reload();
    }
};
Run Code Online (Sandbox Code Playgroud)

在您描述的场景中,data.redirect是undefined. 在这种情况下,您最终会调用window.location.reload(),这当然会重新加载登录页面并清楚地解释您遇到的问题。

以下是所发生情况的逐步细分:

  1. 点击“登录”时会触发提交事件。
  2. 基于浏览器的 POST 被拦截,而是作为 XHR 请求发送。
  3. 服务器登录用户,分配 cookie 并返回 302 响应以重定向到/Home/About.
  4. XHR 内部机制遵循重定向并下拉页面的 HTML /Home/About。
  5. 您的 Javascriptredirect回调被调用,其中data表示对页面的响应/Home/About(text/html响应)。
  6. 最后,当仍在页面上时/Account/Login,页面将按上述方式重新加载。

根据第一个代码片段中显示的设置 jQuery 选择器的方式,您只需将该no-ajax类添加到登录表单中,它就会按预期运行。