RedirectToAction,RedirectToRoute和RedirectToLocal导致应用间歇性挂起

时间:2019-04-25 15:39:53

标签: c# asp.net-core-mvc

这是我几个星期以来一直遇到的问题。具体来说,这似乎发生在我在帐户控制器中的登录操作上。似乎也取决于我用来浏览站点的机器,因为我只在家用机器而不是工作机器上遇到问题。我知道它不是特定于浏览器的,因为两者都使用相同版本的Chrome。它也不是孤立在单个环境中的,因为我可以在本地进行调试并浏览网站本身。

起初,我认为这与我使用异步方法有关,因为我对同步方法的使用并不熟悉。我尝试剥离所有内容并使其完全同步,同时仍获得相同的结果。然后,我尝试将redirecttoaction / route / locals替换为仅返回视图,并且它起作用了。为了进一步确认这是罪魁祸首,我让登录表单遇到了一个完全不同的动作,除了简单的redirecttoaction(“ Index”,“ Home”)以外,它都是空的OTHER,并且该应用程序无限期地挂起。不幸的是,仅点击一个视图并不能满足我的需要,因为在很多情况下,我需要它来击打动作本身。

就其不一致而言,我能够一致地复制它的唯一方法是在本地运行该应用程序并登录。然后关闭浏览器并停止运行该应用程序。然后我再次运行该应用程序>注销>登录,它挂起。

我在stackoverflow和其他站点上进行了大量研究,并尝试了许多不同的建议,例如更改startup.cs中的配置设置,重新安装dll以及其他许多不计其数的事情,没有运气解决这个问题。

这里是构造函数,并且从帐户控制器登录get和post操作

private myContext _context;
private readonly UserManager<ApplicationUser> _userManager;
private readonly SignInManager<ApplicationUser> _signInManager;
private readonly RoleManager<IdentityRole> _roleManager;
private readonly IEmailSender _emailSender;
private readonly ISmsSender _smsSender;
private readonly ILogger _logger;

public AccountController(
    myContext context,
    UserManager<ApplicationUser> userManager,
    SignInManager<ApplicationUser> signInManager,
    RoleManager<IdentityRole> roleManager,
    IEmailSender emailSender,
    ISmsSender smsSender,
    ILoggerFactory loggerFactory)
{
    _context = context;
    _userManager = userManager;
    _signInManager = signInManager;
    _roleManager = roleManager;
    _emailSender = emailSender;
    _smsSender = smsSender;
    _logger = loggerFactory.CreateLogger<AccountController>();
}


// GET: /Account/Login
[HttpGet]
[AllowAnonymous]
public IActionResult Login(string returnUrl = null)
{
    ViewData["ReturnUrl"] = returnUrl;
    return View();
}

// POST: /Account/Login
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
{
    ViewData["ReturnUrl"] = returnUrl;
    if (ModelState.IsValid)
    {
        ApplicationUser user = _userManager.Users.Where(a => a.Email == model.Email).FirstOrDefault();

        if (user != null)
        {
            var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: true);
            if (result.Succeeded)
            {

                _logger.LogInformation(1, "User logged in.");
                var RoleCustomer = _userManager.IsInRoleAsync(user, "Customer");
                var RoleAdmin = _userManager.IsInRoleAsync(user, "Admin");
                if (RoleCustomer.Result)
                {
                    return RedirectToLocal(returnUrl);
                }
                else if (RoleAdmin.Result)
                {

                    return RedirectToRoute(new { controller = "Home", action = "Admin" });
                    //return RedirectToLocal("/Home/Index");
                }
                else
                {
                    ModelState.AddModelError(string.Empty, "Invalid login attempt.");
                    return View(model);
                }

            }
            if (user.EmailConfirmed == false)
            {
                return View("ResendConfirm", new ResendConfirmViewModel() { user = user, returnUrl = returnUrl });
            }

            if (result.IsLockedOut)
            {
                _logger.LogWarning(2, "User account locked out.");
                return View("Lockout");
            }
            else
            {
                ModelState.AddModelError(string.Empty, "Invalid login attempt.");
                return View(model);
            }
        }
        else
        {
            ModelState.AddModelError(string.Empty, "Invalid login attempt.");
            return View(model);
        }


    }

    // If we got this far, something failed, redisplay form
    return View(model);
}

这是登录视图中的登录表单

<form asp-controller="Account" asp-action="Login" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" class="form-horizontal" role="form">
    <h4>Use a local account to log in.</h4>
    <hr />
    <div asp-validation-summary="All" class="text-danger"></div>
    <div class="form-group">
        <label asp-for="Email" class="col-md-2 control-label"></label>
        <div class="col-md-10">
            <input asp-for="Email" class="form-control" />
            <span asp-validation-for="Email" class="text-danger"></span>
        </div>
    </div>
    <div class="form-group">
        <label asp-for="Password" class="col-md-2 control-label"></label>
        <div class="col-md-10">
            <input asp-for="Password" class="form-control" />
            <span asp-validation-for="Password" class="text-danger"></span>
        </div>
    </div>
    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <div class="checkbox">
                <label asp-for="RememberMe">
                    <input asp-for="RememberMe" />
                    @Html.DisplayNameFor(m => m.RememberMe)
                </label>
            </div>
        </div>
    </div>
    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <button type="submit" class="btn btn-default">Log in</button>
        </div>
    </div>
    <p>
        <a asp-action="Register" asp-route-returnurl="@ViewData["ReturnUrl"]">Register as a new user?</a>
    </p>
    <p>
        <a asp-action="ForgotPassword">Forgot your password?</a>
    </p>
</form>

这是启动类

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.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);

            services.AddDbContext<myContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("WebApplication1ContextConnection")));

            services.AddIdentityCore<ApplicationUser>()
                .AddRoles<IdentityRole>()
                .AddEntityFrameworkStores<myContext>()
                .AddSignInManager()
                .AddDefaultTokenProviders();

            services.AddAuthentication(o =>
            {
                o.DefaultScheme = IdentityConstants.ApplicationScheme;
                o.DefaultSignInScheme = IdentityConstants.ExternalScheme;
            })
            .AddIdentityCookies(o => { });

            services.AddSession();

            services.Configure<IdentityOptions>(options =>
            {
                // Default Lockout settings.
                options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
                options.Lockout.MaxFailedAccessAttempts = 5;
                options.Lockout.AllowedForNewUsers = true;
                options.Password.RequireDigit = true;
                options.Password.RequireLowercase = true;
                options.Password.RequireNonAlphanumeric = true;
                options.Password.RequireUppercase = true;
                options.Password.RequiredLength = 6;
                options.Password.RequiredUniqueChars = 1;
                options.SignIn.RequireConfirmedEmail = true;
                options.SignIn.RequireConfirmedPhoneNumber = false;
                options.User.AllowedUserNameCharacters ="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
                options.User.RequireUniqueEmail = true;
            });

            services.ConfigureApplicationCookie(options =>
            {
                //should change this at some point to real access denied. something like Account/AccessDenied
                options.AccessDeniedPath = "/Home/index";
                options.Cookie.Name = "mycookie";
                options.Cookie.HttpOnly = true;
                options.ExpireTimeSpan = TimeSpan.FromMinutes(60);
                options.LoginPath = "/Account/Login";
                // ReturnUrlParameter requires 
                //using Microsoft.AspNetCore.Authentication.Cookies;
                options.ReturnUrlParameter = CookieAuthenticationDefaults.ReturnUrlParameter;
                options.SlidingExpiration = true;
            });

            services.Configure<PasswordHasherOptions>(option =>
            {
                option.IterationCount = 12000;
            });



            // Add application services.
            services.AddTransient<IEmailSender, AuthMessageSender>();
            services.AddTransient<ISmsSender, AuthMessageSender>();
        }

        // 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.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.UseSession();

            app.UseStaticFiles();

            app.UseCookiePolicy();

            app.UseAuthentication();

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

非常感谢您提供的任何帮助/指导。对此,我真的非常感激。如果有什么办法可以提供更多信息,请告诉我。

0 个答案:

没有答案