Reputation: 10509
A client application is uploading an audio file in "chunks" to an MVC3 site. A client uses HttpWebRequest
POST
to do it.
On the server, I have the following controller action:
[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"};
}
Currently, a built-in AspNetMemebershipProvider
is handling the authorization, so the client app has to first authenticate at the logon page, obtain cookie into a CookieContainer
and then make a call to a server to upload a chunk of data.
I want to allow clients to also be able to anonymously upload audio files to the server, without a need to previously register. They the client app code will provide the same guid each time the file is uploaded from the same device.
I want both categories of users to share the same RecieveChunk
action to do it. But they must be authrized either anonymously (with just guid
), or with the logon/pass combination.
Can I have two different controllers linked to two different authentication providers? The third controller, that has [Authorize]
marked action, will allow action if either one provider has given a user a cookie (or some other auth method).
Is it possible in general in ASP.NET MVC3?
Upvotes: 3
Views: 983
Reputation: 7584
As discussed in comments you can create a custom implementation of the FilterAttribute
class and implement the IAuthorizationFilter
interface. For example here is the ChildActionOnlyAttribute
implementation:
[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);
}
}
And here is the RequireHttpsAttribute
implementation:
[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);
}
}
So you could do something like:
[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")
}
}
Upvotes: 1