ASP .NET MVC Защита контроллера / Действие - PullRequest
4 голосов
/ 19 февраля 2010

Если я хочу, чтобы только администратор получил доступ к действию, называемому «ManagerUser», я знаю, что могу сделать это:

[Authorize( Roles = Constants.ROLES_ADMINISTRATOR )]
public ActionResult ManageUser( string id )
{
}

Что если я хочу дать всем доступ, кроме администратора?Я не хочу писать все роли там на функции: |.

Любые рекомендации / выходы?

Ответы [ 3 ]

11 голосов
/ 19 февраля 2010

Вы можете создать свой собственный атрибут Authorize, например «AuthorizeAllExceptAdmin».Внутри этого класса вам просто нужно проверить, был ли текущий пользователь администратором, и если они отклонили его, в противном случае примите его.

Вот хороший учебник , но вы 'Вероятно, в итоге получится что-то вроде:

public class AuthorizeAllExceptAdmin : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        return !httpContext.User.IsInRole(Constants.ROLES_ADMINISTRATOR);
    }
}

Тогда ваш метод контроллера станет следующим:

[AuthorizeAllExceptAdmin] 
public ActionResult SomethingOnlyNonAdminsCanDo() 
{ 
} 

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

public class DoNotAuthorize : AuthorizeAttribute
{
    private IEnumerable<string> _rolesToReject;

    public DoNotAuthorize(IEnumerable<string> rolesToReject)
    {
        _rolesToReject = rolesToReject;        
    }

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        foreach (var role in _rolesToReject)
        {
            if (httpContext.User.IsInRole(role))
                return false;
        }

        return true;
    }
}

Тогда ваш метод контроллера становится следующим:

[DoNotAuthorize(new [] {Constants.ROLES_ADMINISTRATOR})] 
public ActionResult SomethingOnlyNonAdminsCanDo() 
{ 
} 

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

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

5 голосов
/ 19 февраля 2010

Помимо создания пользовательского атрибута AuthorizeAttribute, предложенного manu, вы можете использовать PrincipalPermission с действием Deny-SecurityAction:

[PrincipalPermission(SecurityAction.Deny, Role="Administrator")]
1 голос
/ 19 февраля 2010

В моем приложении я не использую роли, поэтому мне нужно запросить базу данных, чтобы определить, есть ли у пользователя доступ или нет.Преимущества приведенного ниже кода в том, что вы можете очень легко перенаправить пользователя на определенное действие.Я объяснил код в своем блоге на http://blog.athe.la/2009/12/implementing-permission-via-windows-authentication-in-asp-mvc-using-action-filters/

public class DatabaseRepository()
{
    private readonly DatabaseDataContext db = new DatabaseDataContext();

    public bool UserHasPermission(string userLogon) {
        return (from permission this.db.Permissions
                where permission.HasPermissionSw == true
                select permission).Contains(userLogon);
    }
}

public class UserHasPermission: ActionFilterAttribute
{
    private readonly DatabaseRepository databaseRepository = new DatabaseRepository();
    private readonly string redirectAction;
    public UserHasPermission(string redirectTo)
    {
        this.redirectAction = redirectTo;
    }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        string userLogon = filterContext.HttpContext.User.Identity.Name;
        if (!this.databaseRepository.UserHasPermission(userLogon))
        {
            string routeController = filterContext.Controller.ControllerContext.RouteData.Values["controller"];
            filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { controller = routeController, action = this.redirectAction }));
        }
    }
}

Ваш контроллер будет выглядеть примерно так:

[UserHasPermission("NoAccess")]
public ActionResult SecretArea()
{
    // run all the logic
    return View();
}

public ActionResult NoAccess()
{
    return View();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...