Сбой аутентификации форм ASP.Net MVC с DefaultModelBinder при вызове из jQuery - PullRequest
0 голосов
/ 11 апреля 2019

Я занимаюсь разработкой приложения Asp.Net MVC с FormsAuthentication. Проверки формы выполняются в jquery и jquery, а затем в методе действия $ .post to MVC. Каждый запрос проверяется этим классом:

 [Serializable]
    public class CachedModelBinder : DefaultModelBinder
    {
        public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {

            object model = base.BindModel(controllerContext, bindingContext);
            HelperMethods.ValidateLogin(controllerContext.HttpContext.Session, controllerContext.HttpContext.User.Identity.IsAuthenticated, controllerContext.HttpContext.Request.Cookies[FormsAuthentication.FormsCookieName], (BaseViewModel)model, controllerContext.HttpContext.Request.Url.AbsoluteUri, controllerContext.HttpContext);

            return model;
        }
    }

public static bool ValidateLogin(HttpSessionStateBase session, bool is_authenticated, HttpCookie authCookie, BaseViewModel model, string Uri, HttpContextBase context)
        {
            if (session != null)
            {
                if (session["ResId"] == null || !is_authenticated)
                {
                    if (is_authenticated)
                        FormsAuthentication.SignOut();

                    if (session["ResId"] != null)
                        session["ResId"] = null;


                    return false;
                }
                else
                {
                    LoadRestaurant(authCookie, model);
                    return true;
                }
            }
            else
            {
                return false;
            }
        }

Я не уверен, как этот метод запущен, и я не вижу стека вызовов до этого метода. Может кто-нибудь сказать мне, как это называется? У меня есть три класса viewmodel (BaseModel, HomeModel, RestaurantModel) для двух представлений (Home / Index.cshtml и Business / Index.cshtml)

Так я регистрирую модели в файле global.asax.cs. Я не регистрирую BaseModel ниже, потому что он не передается в качестве входных данных для любого из методов действия.

protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            XmlConfigurator.Configure();

            ModelBinders.Binders.Add(typeof(HomeModel), new CachedModelBinder());
            ModelBinders.Binders.Add(typeof(RestaurantModel), new CachedModelBinder());          
        }

Код модели выглядит следующим образом

 public class BaseModel
    {
        public bool IsAuthenticated { get; set; }
        public string PageTitle { get; set; }
        public string UserName { get; set; }
        public string Password{ get; set; }       
        public Business Business { get; set; }      
        public int BusinessId { get; set; }
    }  

public class HomeModel : BaseModel
    {
    } 
public class RestaurantModel : BaseModel
    {
        public int RestaurantId { get; set; }
        public string RestaurantEmail { get; set; }
        public Business Restaurant{ get; set; }

    }

HomeController.cs ->

public ActionResult Index(HomeModel model)
        {
            if (model.IsAuthenticated) { return RedirectToAction("Index", "Restaurant"); }

            // code goes here
            return View(model);
        }

[ControllerLogInterceptor]
        public ActionResult Login(HomeModel model)
        {
           // Login verification code goes here
FormsAuthentication.SetAuthCookie(res.ID.ToString(), false);


                    Session["ResId"] = bus.ID;
            return Json;
        }

RestaurantController.cs ->

 public ActionResult Index(RestaurantModel model)
        {
            if (model.Business == null || model.Business.ID < 1)
            {
                FormsAuthentication.SignOut();
                RedirectToAction("Index", "Home");
            }
            else
            {
           // next view code goes here
}
            return View(model);
        }

jQuery / HTML-код

 <form id="loginForm" method="post">                        
                        <div class="form-group">                         
                            <input type="text" id="UserName" name="UserName" class="form-control col-sm-3" />
                            <div class="invalid-feedback" id="validationFileNumber">
                                <span>UserName is required</span>
                            </div>
                        </div>
                        <div class="form-group">
                            <input type="text" id="Password" name="Password" class="form-control col-sm-1"  />
                            <div class="invalid-feedback" id="validationPin">
                                <span>Password is required</span>
                            </div>
                        </div>
                        <span class="invalid-feedback" id="divError"><br /></span>
                        <button type="submit" class="btn btn-primary disabled" id="btnLogin">Continue</button>
                        <input type="text" class="form-group valid-feedback">
                    </form>

$('#btnLogin').click(function () {       

      // Form validation happens before
        var model = $('#loginForm').serialize();
        $.post('/Home/Login', model)
            .done(function (response, status, jqXhr) {              
                    window.location = '/Restaurant';
                }
            })
            .fail(function (response, status, jqXhr) {

            })
    });

После успешного входа в систему метод BindModel снова вызывается с HomeModel и не проходит проверку подлинности. Также метод bindModel вызывается дважды.

Приложение должно аутентифицировать пользователя для других страниц.

...