ASP.NET MVC, атрибут «Требуется билет» - PullRequest
6 голосов
/ 22 декабря 2010

Я пытаюсь создать систему, которая позволяет пользователям выполнять определенные действия, но их учетная запись должна иметь определенный «билет» каждый раз, когда они это делают. Например, предположим, что они хотят создать Product, им понадобится CreateProductTicket.

Конечно, я мог бы просто сделать это с помощью некоторых «если», но я хочу попробовать более надежное решение. Моя структура выглядит примерно так ...

interface ITicket<T> where T : ITicketable
{
}

Моя основная цель - создать Атрибут, например, как показано ниже.

public class TicketRequiredAttribute : Attribute
{
 public TicketRequiredAttribute(ITicket<T> ticket)
 {
  if(ticket == null) 
    return;
  }
}

И чтобы можно было украсить контроллер или Действиями репозитория с этим. Так как ...

ProductsControlller

[TicketRequired(CreateProductTicket)]
public ActionResult CreateProduct(Product product)
{
 // ... **I am unsure how to tell if TicketRequired was true or not**
}

Задача 1

Я недостаточно знаком с атрибутами, чтобы знать, как определить, встречен ли TicketRequired или нет. Может ли кто-нибудь просветить меня об этом?

Задача 2

Проблема, с которой я сталкиваюсь, связана с запросами к базе данных. Я хочу иметь возможность проверить пользователя (IMembershipRepository имеет метод GetUser), но я не совсем уверен, как это сделать с помощью атрибута.

Используя Castle.Windsor, я настроил Dependency Injection, чтобы вводить репозитории в контроллеры. Я полагаю, что мог бы передать IMembershipRepository через конструктор TicketRequired, но у меня есть ощущение, что оно станет очень грязным и крайне нестабильным. Есть ли более логичный способ подойти к этому?

Ответы [ 2 ]

6 голосов
/ 22 декабря 2010

Ты почти у цели. Вы можете найти более подробную информацию на http://www.asp.net/mvc/tutorials/understanding-action-filters-cs

Я бы использовал атрибут только в действии, поскольку на веб-сайте я делаю все свои авторизации.

Вот возможное решение. Я не проверял это, но это должно работать. Вам нужно будет проверить способ перенаправления, но я не уверен, что это правильно.

 public class TicketRequiredActionFilter : ActionFilterAttribute
 {
        private Type _ticketType;

  public TicketRequiredAttribute(Type ticketType)
  {
        _ticketRequired = ticketType;     
  }

  public override void OnActionExecuting(ActionExecutingContext filterContext)
  {
     UserServices userServices = GetUserServicesViaDIContainer(); // you'll need to figure out how to implement this 
     string userId = filterContext.HttpContext.User.Identity.Name
     bool hasTicket = userServices.HasTicket(_ticketType, (int)userId); // again, you'll need to figure out the exact implementation
     if(!hasTicket)
     {
        filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary { { "controller", "Home" }, {"action", "NoPermission" } })
     }
     else
     { 
        base.OnActionExecuting(filterContext);
     }     
  }
}

В вашем контроллере:

[TicketRequiredActionFilter(typeof(CreateProductTicket))]
public ActionResult MyMethod()
{
    // do stuff as if the person is authorized and has the ticket
}

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

1 голос
/ 22 декабря 2010

Это очень похоже на роли пользователя.

Как вы справляетесь с членством пользователя? Если вы используете встроенное членство asp.net, вы можете использовать роли. Таким образом, у каждого пользователя будет определенное количество ролей в вашем случае, одна из которых будет «CreateProductTicket», тогда вы можете украсить свое действие или контроллер атрибутом Authorize. Что-то вроде:

[Authorize(Roles="CreateProductTicket")]
public ActionResult CreateProduct(Product product)

Если пользователь не имеет роли или не авторизован, он может получить доступ к действию.

...