2014-02-10 5 views
0

Я просматривал много SO и других страниц, но до сих пор не смог найти аналогичный случай.Успех аутентификации ASP.NET MVC4, но роли отсутствуют после сборки проекта

Мое приложение использует SimpleMembership. В нем есть пользовательское меню на основе ролей, и большинство действий выполняется с атрибутом [Авторизовать (Roles = "aaa, bbb")].

После того как приложение закроет или покинет браузер в течение некоторого времени, пользователь будет перенаправлен на страницу входа в систему по любой ссылке. Странно то, что имя входа по-прежнему остается действительным для показа, но без имен ролей.

Пользователи имеют доступ к действиям с атрибутом [Авторизовать] в приведенной выше ситуации. Мне интересно, нет ли чего-то, чего я не вижу, или я могу сделать, чтобы сохранить информацию о роли до тех пор, пока аутентификация действительна?

Вот код от действия контроллера для отображения меню:

public ActionResult Menu() 
    { 
     if (Roles.IsUserInRole("Admin")) 
     { 
      return View("MenuAdmin"); 
     } 
     if (Roles.IsUserInRole("Advising")) 
     { 
      return View("MenuAdvising"); 
     } 
     if (Roles.IsUserInRole("StudentDevelopment")) 
     { 
      return View("MenuStudentDevelopment"); 
     }... 

Customized _logonPartial для отображения имени пользователя и роли

> @if (Request.IsAuthenticated) { 
    <text> 
     Logged in: @Html.ActionLink(User.Identity.Name, "Manage", "Account", routeValues: null, htmlAttributes: new { @class = "username", title = "Manage" }) as 
     @String.Join(",", Roles.GetRolesForUser(User.Identity.Name)) 
     @using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm" })) { 
      @Html.AntiForgeryToken() 
      <a href="javascript:document.getElementById('logoutForm').submit()">Log off</a> 
     } 
    </text> 

ответ

1

Информация роль доступна до тех пор, как пользователь вошел в систему. В вашем случае вы звоните:

Roles.GetRolesForUser(User.Identity.Name) 

, чтобы получить список ролей. Это фактически попадает в базу данных, чтобы получить роли, поэтому, пока нам доступно имя пользователя в Identity, оно вернет роли, предполагая, что у пользователя есть роли, назначенные им. И имя пользователя должно быть доступно, если идентификатор пользователя аутентифицирован. Вы проверяете Request.IsAuthenticated. Вероятно, лучше проверить User.Identity.IsAuthenticated.

Существует способ получить роли без запроса базы данных с использованием претензий. И вообще я бы не поставил такую ​​логику и доступ к системным переменным в ваших Представлениях. Я бы использовал этот подход в своем действии контроллера, чтобы получить роли.

 var prinicpal = (ClaimsPrincipal)Thread.CurrentPrincipal; 
     var roles = prinicpal.Claims.Where(c => c.Type == ClaimTypes.Role).Select(c => c.Value); 
     ViewBag.Roles = roles; 

Либо поставить необходимую вам информацию в своих соображениях по в ViewBag или создать модель, которая передается в View. Такой подход для получения ролей не требует обратной поездки в базу данных.

Обновление Адрес Комментарии

Стандарт AuthorizeAttribute для MVC 4 использует сконфигурированный членство и роли поставщика (в вашем случае SimpleMembership), чтобы получить роль. Он не принимает претензий, когда они используются, поэтому каждый раз он поступает в базу данных. Фактически, он должен дважды обращаться к базе данных, чтобы получить идентификатор пользователя для входа в систему, а затем получить роли на основе этого идентификатора пользователя. Не очень эффективно. Удивительно, но это делает это, даже если вы не передаете какие-либо роли в качестве параметров, где нет необходимости разрешать пользователя против ролей и просто проверять подлинность. Я проверил это с помощью профилировщика.

Чтобы сделать его более эффективным и не требовать перехода к базе данных, вы можете написать собственный атрибут AuthorizeAttribute для использования претензий. Here is an article that describes how to do this, со ссылками на пример исходного кода.

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

+0

Спасибо за ваш ответ. Ситуация такова: после каждой сборки пользователи будут перенаправлены на страницу входа при доступе к действиям '[Authorize (Roles =" XXX, BBB)). Это не происходит в действиях '[Authorize]' (пользователь может получить доступ после сборки). По моим наблюдениям, пользователи все еще вошли в систему после сборки, но роли отсутствуют. это проблема тайм-аута подключения к базе данных? Интересно, есть ли способ сохранить роли при выполнении атрибута действия. Спасибо – horizon1711

+0

См. Мой обновленный ответ. –

+0

Я попытался создать приложение, предназначенное для имитации ситуации бездействия, которая теряет роли. В настоящее время решена «потеря ролей, но завершена» - это тайм-аут пула приложений IIS. Увеличен тайм-аут, и он отлично работает. Спасибо за вашу помощь. – horizon1711

Смежные вопросы