Возможно ли наличие нескольких поставщиков аутентификации одновременно в приложении ASP.NET MVC3? - PullRequest
3 голосов
/ 19 января 2012

Клиентское приложение загружает аудиофайл в виде фрагментов на сайт MVC3. Для этого клиент использует HttpWebRequest POST.

На сервере у меня есть следующие действия контроллера:

  [Authorize]
  [HttpPost]
  public JsonResult RecieveChunk(string id, [ModelBinder(typeof(AudioChunkModelBinder))] byte[] audio)
        {
            //Process chunk

            var chunk = new AudioChunk
            {
                ThoughtId = Guid.Parse(id),
                Data = audio
            };

            //Process chunk by BL

            return new JsonResult {Data = "Success"};
        }

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

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

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

Могу ли я иметь два разных контроллера, связанных с двумя разными провайдерами аутентификации? Третий контроллер, имеющий помеченное действие [Authorize], разрешит действие, если один из провайдеров предоставил пользователю cookie (или другой метод аутентификации).

Возможно ли это вообще в ASP.NET MVC3?

1 Ответ

1 голос
/ 01 февраля 2012

Как обсуждалось в комментариях, вы можете создать собственную реализацию FilterAttribute класса и реализовать интерфейс IAuthorizationFilter . Например, вот реализация ChildActionOnlyAttribute:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public sealed class ChildActionOnlyAttribute : FilterAttribute, IAuthorizationFilter
{
  public void OnAuthorization(AuthorizationContext filterContext)
  {
    if (filterContext == null)
      throw new ArgumentNullException("filterContext");
    if (!filterContext.IsChildAction)
      throw Error.ChildActionOnlyAttribute_MustBeInChildRequest(filterContext.ActionDescriptor);
  }
}

А вот реализация RequireHttpsAttribute:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class RequireHttpsAttribute : FilterAttribute, IAuthorizationFilter
{
  public virtual void OnAuthorization(AuthorizationContext filterContext)
  {
    if (filterContext == null)
      throw new ArgumentNullException("filterContext");
    if (filterContext.HttpContext.Request.IsSecureConnection)
      return;
    this.HandleNonHttpsRequest(filterContext);
  }

  protected virtual void HandleNonHttpsRequest(AuthorizationContext filterContext)
  {
    if (!string.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
      throw new InvalidOperationException(MvcResources.RequireHttpsAttribute_MustUseSsl);
    string url = "https://" + filterContext.HttpContext.Request.Url.Host + filterContext.HttpContext.Request.RawUrl;
    filterContext.Result = (ActionResult) new RedirectResult(url);
  }
}

Так что вы можете сделать что-то вроде:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public sealed class CustomAuthorizeAttribute : FilterAttribute, IAuthorizationFilter
{
  public void OnAuthorization(AuthorizationContext filterContext)
  {
    if (filterContext == null)
      throw new ArgumentNullException("filterContext");

    var guidPresent = CheckForGuid();

    if (!filterContext.HttpContext.User.Identity.IsAuthenticated && !guidPresent)
      throw new InvalidOperationException("Must authenticate properly")
  }
}
...