Модальный вход без перенаправления страницы ASP.Net MVC не может пройти аутентификацию в частичном представлении

После успешного входа в систему Account Controller я пытаюсь отобразить _LoginPartial.cshtml, чтобы переключить текст в моей панели навигации с «Вход» на «Выход» («выход» находится в форме и имеет маркер защиты от конфиденциальности. Я вызов RenderRazorViewToString для вызова частичного представления и передачи его моему ответу ajax, но «Request.Isauthenticated» всегда имеет значение false в частичном представлении, поэтому текст никогда не меняется на «Выход из системы». Может быть, я просто не понимаю, как работает аутентификация? или, может быть, это как-то связано с моим токеном антифальсификации из вызова Ajax.

Весь код ниже.

AccountController.cs

    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> LoginJson(string email, string password, bool rememberme)
    {
        ..code here left blank

        var result = await SignInManager.PasswordSignInAsync
                     (userName, password, rememberme, shouldLockout: false);
        switch (result)
        {
            case SignInStatus.Success:
                return Json(new { error = false, message = RenderRazorViewToString("_LoginPartial", null) });

            ..code here left blank
        }
    }

    private string RenderRazorViewToString(string viewName, object model)
    {
        if (model != null)
            ViewData.Model = model;

        using (var sw = new StringWriter())
        {
            var viewResult = ViewEngines.Engines.FindPartialView(ControllerContext,
                                                                     viewName);
            var viewContext = new ViewContext(ControllerContext, viewResult.View,
                                         ViewData, TempData, sw);
            viewResult.View.Render(viewContext, sw);
            viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);
            return sw.GetStringBuilder().ToString();
        }
    }

_LoginPartial.cshtml

//Request.IsAuthenticated is false when calling it from RenderRazorViewToString
@if (Request.IsAuthenticated) { using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm"})) { @Html.AntiForgeryToken()

<ul class="nav navbar-nav navbar-right">
  <li>@Html.ActionLink("Create Yoga Band!", "Create", "YogaSpace")</li>
  <li class="dropdown">
    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">Menu<span class="caret"></span></a>
    <ul class="dropdown-menu" role="menu">
      <li>@Html.ActionLink("User", "UserProfile", "Account")</li>
      <li>@Html.ActionLink("Profiles", "Edit", "Student")</li>
      <li>@Html.ActionLink("Yoga Spaces", "Index", "YogaSpace")</li>
      <li><a href="#">Schedules</a>
      </li>
      <li><a href="#">Invite Friends!</a>
      </li>
    </ul>
  </li>
  <li><a href="javascript:document.getElementById('logoutForm').submit()">Log off</a>
  </li>
</ul>
} } else {
<ul class="nav navbar-nav navbar-right">
  <li>@Html.ActionLink("Create Yoga Space!", "Create", "YogaSpace")</li>
  <li>@Html.ActionLink("Register", "Register", "Account", routeValues: null, htmlAttributes: new { id = "registerLink" })</li>
  <li>@Html.ActionLink("Log in", "Login", "Account", routeValues: new { returnUrl = Request.RawUrl }, htmlAttributes: new { id = "loginLink" })</li>
</ul>
}

Вот вызов ajax, который я делаю, чтобы нажать контроллер для входа в систему

LoginIntoStd: function(email, password, rememberme, antiForgeryToken,
  successCallback, failureCallback) {
  var data = {
    "__RequestVerificationToken": antiForgeryToken,
    "email": email,
    "password": password,
    "rememberme": rememberme
  };
  $.ajax({
      url: "/Account/LoginJson",
      type: "POST",
      data: data
    })
    .done(function(response) {
      if (response.error) {
        failureCallback(response.message);
      } else {
        successCallback(response.message);
      }
    })
    .fail(function(jqxhr, textStatus, errorThrown) {
      failureCallback(errorThrown);
    });
}

Вот успешный метод обратного вызова

loginSuccess: function(message) {
  // close the modal
  $('#ModalLogin').modal('hide');
  // change the navbar items to show 'log out'
  $('#loginPartial').replaceWith(message);
}


person user1186050    schedule 11.09.2015    source источник


Ответы (1)


На самом деле я не тестировал код, но мое первое предположение состоит в том, что это как-то связано с потоком. Я думаю, что объект Request и его свойство IsAuthenticated генерируются во время самого запроса, что происходит до фактической обработки входа. Я бы посоветовал вам сделать следующее, это также немного очистит ваш код:

Разделите _LoginPartial.cshtml на два файла. Одним из них является _LoginPartial.cshtml, и он будет содержать код только для неавторизованных пользователей (блок "else"). Создайте еще один файл с именем _LogoutPartial.cshtml, в который вы поместите содержимое только для авторизованных пользователей.

В вашем switch из SignInManager.PasswordSignInAsync результата вы возвращаете либо одно частичное, либо другое.

В качестве альтернативы, вы можете попробовать проверить User.Identity.IsAuthenticated вместо Request.IsAuthenticated в вашем представлении, возможно, оно будет установлено правильно по времени, но это только предположение.

person thmshd    schedule 11.09.2015
comment
привет Томас, спасибо за ответ. Я попытался заменить «Request.Isauthenticated» на «User.Identity.IsAuthenticated», но это, похоже, ничего не дало. Я также попробовал ваш другой вариант и вытащил весь код из блока if и вставил его в частичное представление. Затем я просто отобразил частичное представление в операторе switch, и это отлично работает, и отображается выход из системы, НО антифальсификация токена в частичном представлении выдает ошибку, когда я пытаюсь выйти из системы. Есть предположения!? - person user1186050; 11.09.2015
comment
@user1186050 user1186050 Извините, я не очень разбираюсь в antiforgerytoken, но кажется, что токен, сгенерированный в вашем Ajax-вызове, больше недействителен при проверке с помощью созданного ранее контекста страницы. Не уверен, что это полезно, но посмотрите это: блог .rohit-lakhanpal.info/2013/10/ или поищите antiforgerytoken ajax, у многих с этим проблемы. - person thmshd; 11.09.2015