Как ограничить доступ к определенным страницам в ASP.NET MVC?

Я хочу заблокировать доступ к странице РЕДАКТИРОВАНИЯ пользователя (например, /user/pure.krome/edit), если

а) Identity.IsAuthenticated = false

или они аутентифицированы, но

б) Idenitity.Name! = имя пользователя страницы пользователя, которую они пытаются редактировать
c) Identity.UserType ()! = UserType.Administrator // Это похоже на роль, без использования RoleProviders.

Я предполагаю, что вы можете украсить контроллер или метод действия контроллера чем-то (ами), но я просто не уверен, что?


person Pure.Krome    schedule 03.06.2009    source источник


Ответы (3)


Посмотрите на AuthorizeAttribute.

ASP.Net MVC: можно ли переопределить атрибут AuthorizeAttribute?

person Daniel A. White    schedule 03.06.2009

Настраиваемый атрибут, производный от AuthorizeAttribute, - это то, что Я для этого делаю. Переопределите метод OnAuthorize и реализуйте ваша собственная логика.

public class OnlyUserAuthorizedAttribute : AuthorizeAttribute
{
    public override void OnAuthorize( AuthorizationContext filterContext )
    {
        if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            filterContext.Result = new HttpUnauthorizeResult();
        }
        ...
    }
}
person tvanfosson    schedule 03.06.2009
comment
Интересно ... но ... я знаю, что мне нужно заменить свою логику на вашу. Но ваш код отвечает только на часть (а). Я также могу проверить (c). Но я понятия не имею, как код мог знать, что проверять (б). У меня есть Identity.Name ... но как этот атрибут - в этот момент - знает, что такое данные представления? или любые данные в методе действия (который, как я полагаю, еще не был запущен ... потому что сначала обрабатываются атрибуты. - person Pure.Krome; 03.06.2009
comment
Параметр AuthorizationContext включает ссылки на Controller, HttpContext, ResultContext, RouteData и Result. Вы должны получить все необходимое из RouteData. В качестве обобщения добавьте свойство к вашему атрибуту, которое позволяет вам указать ключ данных маршрута, который будет использоваться для имени пользователя. Вам нужно будет выполнить работу с БД, чтобы независимо проверить тип пользователя. Возможно, вы захотите иметь два конструктора: один, который принимает интерфейс контекста / уровня вашей базы данных, а другой, который не принимает параметров и создает контекст / уровень базы данных по умолчанию. Используйте первое в модульном тестировании. - person tvanfosson; 03.06.2009

Я реализовал следующий атрибут ActionFilterAttribute, и он работает как для аутентификации, так и для ролей. Я храню роли в своих таблицах БД следующим образом:

  • Пользователь
  • UserRole (содержит внешние ключи UserID и RoleID)
  • Роль
public class CheckRoleAttribute : ActionFilterAttribute
{
    public string[] AllowedRoles { get; set; }


    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        string userName = filterContext.HttpContext.User.Identity.Name;

        if (filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            if (AllowedRoles.Count() > 0)
            {
                IUserRepository userRepository = new UserRepository();
                User user = userRepository.GetUser(userName);
                bool userAuthorized = false;
                foreach (Role userRole in user.Roles)
                {
                    userAuthorized = false;
                    foreach (string allowedRole in AllowedRoles)
                    {
                        if (userRole.Name == allowedRole)
                        {
                            userAuthorized = true;
                            break;
                        }
                    }
                }
                if (userAuthorized == false)
                {
                    filterContext.HttpContext.Response.Redirect("/Account/AccessViolation", true);
                }
            }
            else
            {
                filterContext.HttpContext.Response.Redirect("/Account/AccessViolation", true);
            }
        }
        else
        {
            filterContext.HttpContext.Response.Redirect(FormsAuthentication.LoginUrl + String.Format("?ReturnUrl={0}", filterContext.HttpContext.Request.Url.AbsolutePath), true);
        }


    }

Я называю это так ...

    [CheckRole(AllowedRoles = new string[] { "admin" })]
    public ActionResult Delete(int id)
    {
        //delete logic here
    }
person mikerennick    schedule 04.06.2009
comment
В первой строке выше я хотел сказать аутентификация и роли - person mikerennick; 04.06.2009
comment
Микеренник, вы занимаетесь кешированием пользователей или ролей? - person Pure.Krome; 05.06.2009
comment
Я не использую кеширование, но не вижу причин, по которым список ролей, назначенных пользователю, нельзя было кэшировать. Вы можете обновлять кеш при внесении изменений в назначенные роли. Приведенный выше код не имеет отношения к кешированию пользователей, поскольку я просто просматриваю httpcontext для текущего пользователя. Я также должен упомянуть, что добавление проверки для разрешенных пользователей в принципе такое же, как и проверка для разрешенных ролей. - person mikerennick; 05.06.2009