asp.net MVC 3 применение AuthorizeAttribute к областям

В настоящее время я пишу сайт Admin MVC 3, и каждый пользователь имеет доступ только к определенным частям сайта.

Области моего сайта такие же, как и роли пользователей, поэтому я хотел бы поместить AuthorizeAttribute в каждую область, используя имя области в качестве параметра в роли.

Пока что у меня есть это, чтобы работать, когда я жестко кодирую проверку каждой области, но я хотел бы просто пройтись по всем областям и применить фильтр авторизации. (я использую это как свой собственный FilterProvider - http://www.dotnetcurry.com/ShowArticle.aspx?ID=578)

Мой код на данный момент («Gcm» - это одна из моих областей, а также роль):

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new HandleErrorAttribute());
    // for all controllers, run AdminAuthorizeAttribute to make sure they're at least logged in
    filters.Add(ObjectFactory.GetInstance<AdminAuthorizeAttribute>());

    AdminAuthorizeAttribute gcmAuthroizeAttribute = ObjectFactory.GetInstance<AdminAuthorizeAttribute>();
    gcmAuthroizeAttribute.Roles = "Gcm";

    var provider = new FilterProvider();
    provider.Add(
        x =>
        x.RouteData.DataTokens["area"] != null && x.RouteData.DataTokens["area"].ToString() == "Gcm"
            ? gcmAuthroizeAttribute
            : null);
    FilterProviders.Providers.Add(provider);
}

Кто-нибудь знает, как получить все области моего приложения, чтобы я мог просто прокручивать их, а не жестко кодировать каждую область?

Или, если у кого-то есть лучшее представление о том, как авторизовать для каждой области, это было бы признательно.

Спасибо за помощь, Саан


person Saan    schedule 16.05.2011    source источник


Ответы (3)


Вы можете создать базовый контроллер для каждой области и поместить атрибут авторизации над базовым классом. Таким образом, вы можете передать параметр области для каждого базового контроллера области.

person mccow002    schedule 30.06.2011

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

Использование:

[AjaxAuthorize(AjaxRole = "Administrators")]
public JsonResult SaveAdministrativeUser(v.... )

Код:

 public class AjaxAuthorizeAttribute : AuthorizeAttribute
    {
        private class HttpAuthorizeFailedResult : ActionResult
        {
            public override void ExecuteResult(ControllerContext context)
            {                
                // Set the response code to 403.   Membership.Provider.Name == "UnitArchiveMembershipProvider"
                context.HttpContext.Response.StatusCode = context.HttpContext. User.Identity is WindowsIdentity ?  401 : 403; 
            }
        }

        public string AjaxRole { get; set;}

        public AjaxAuthorizeAttribute()
        {
            AjaxRole = "Users";
        }

        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            if (string.IsNullOrEmpty(MvcApplication.Config.DBSettings.Database))
            {
                return true;
            }

            //When authorize parameter is set to false, not authorization should be performed.
            UnitArchiveData db = DataContextFactory.GetWebRequestScopedDataContext<UnitArchiveData>(MvcApplication.Config.DBSettings.GetConnectionString());            


            if (httpContext.User.Identity.IsAuthenticated)
            {
                login_data user = db.login_datas.Where(n => n.EmailAddress == httpContext.User.Identity.Name).FirstOrDefault();
                if (user != null)
                {
                    return user.cd_login_role.RoleName == "Administrators" || user.cd_login_role.RoleName == AjaxRole;
                }
            }

            return false;

        }

        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest())
            {
                //Ajax request doesn't return to login page, it just returns 403 error.
                filterContext.Result = new HttpAuthorizeFailedResult();
            }
            else
                base.HandleUnauthorizedRequest(filterContext);
        }
    }
person Sergei Golos    schedule 16.05.2011
comment
Привет Сергей. Спасибо за ответ, но я уже создал свой собственный атрибут авторизации, и он отлично работает. Мне просто нужно уметь передавать соответствующие роли в каждой из сфер. Я не хочу помещать атрибут на каждый контроллер. Я ищу что-то, что можно настроить автоматически, когда кто-то добавляет новую область. - person Saan; 16.05.2011
comment
Ага, посмотри, как я это делаю. Переменная AjaxRole передается в настраиваемый AuthorizeAttribte. Автоматически может быть непросто, но добавление [AjaxAuthorize (AjaxRole = Administrators)] в заголовок функции не так уж сложно и решает вашу проблему. - person Sergei Golos; 16.05.2011
comment
Но это означает, что любой, кто добавляет код в проект (а некоторые будут сторонними разработчиками), должен будет убедиться, что в контроллер добавлен правильный атрибут авторизации. Я ищу способ убедиться, что используется правильная авторизация, несмотря ни на что. - person Saan; 17.05.2011
comment
Разве это не включает соглашение об именах, которому должен будет следовать кто-то другой? Я имею в виду, что вы знаете, что вам нужно лучше, чем я, но именно так Microsoft порекомендовала бы использовать AuthorizeAttribute. - person Sergei Golos; 17.05.2011
comment
Не совсем - когда я добавляю третью зону для вечеринок - частью этого будет добавление роли. Я думаю, что это сработает, если я смогу просто получить список всех областей сайта, а затем просмотреть их все. - person Saan; 17.05.2011

Когда я исследовал отдельную проблему, я наткнулся на Как передать параметры в настраиваемый ActionFilter в ASP.NET MVC 2?

Этот пример атрибута можно изменить, чтобы проверить текущую область контроллера.

public class CustomAuthorizeAttribute : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        RouteData routeData = filterContext.RouteData;

        // check if user is allowed on this page
        if (SessionFactory.GetSession().Contains(SessionKey.User))
        {
            User user = (User)SessionFactory.GetSession().Get(SessionKey.User);
            string thisArea = routeData.DataTokens["area"].ToString();

            // if the user doesn't have access to this area
            if (!user.IsInRole(thisArea))
            {
                HandleUnauthorizedRequest(filterContext);
            }
        }

        // do normal OnAuthorization checks too
        base.OnAuthorization(filterContext);
    }
}

Затем я применяю свой настраиваемый атрибут авторизации ко всем контроллерам, подобным этому в Global.asax:

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new HandleErrorAttribute());
    // for all controllers, run CustomAuthorizeAttribute to make sure they're at logged in and have access to area
    filters.Add(ObjectFactory.GetInstance<CustomAuthorizeAttribute>());
}

Спасибо всем кто ответил

Саан

person Saan    schedule 14.09.2011
comment
Предупреждение: это небезопасная практика. Я изучал эту же область и обнаружил, что это не рекомендуется. Области - это концепция маршрутизации, но контроллеры могут быть найдены и захвачены , даже если область не указана. Леви объясняет здесь - person Quango; 25.01.2013