Reputation: 11410
I am using a custom Membership Provider. Everything is working great. However, in my web.config file I have "deny users" enabled so the entire site is locked down.
This works great. The user is redirected to the login page.
Now, I have a few controllers/actions that I want to allow anonymous access. About page, password reset, etc.
The only way I can figure out how to do this is to UNLOCK the entire site, put [Authorize] attributes on every controller and remove them for the controller/actions I want anonymous.
This seems backwards to me. I prefer to lock everything down by default and unlock what is anonymous.
Is there a way around this?
Thanks!
Upvotes: 3
Views: 1013
Reputation: 532435
I can think of alternative ways to implement this, but they all involve using a customized AuthorizeAttribute. One way to do this would be to have a base controller using said customized AuthorizeAttribute that all of your controllers derive from. This attribute would be customized to prevent anonymous (and unauthorized) access to an action unless it's controller or the action itself has been decorated with another attribute -- say the AnonymousEnabledAttribute. All of your controllers would derive from this controller and thus inherit it's standard "no anonymous by default" behavior. You would then simply decorate the controllers/actions you want to be anonymous with the AnonymousEnabledAttribute -- providing the override for that controller or action. Or, for a controller, simply don't inherit from the protected controller and all of it's actions become public.
Oh, and your whole site would have to remain open.
[OverridableAuthorize]
public abstract class ProtectedController : Controller
{
}
public class MostlyProtectedController : ProtectedController
{
public ActionResult ProtectedAction()
{
}
[AnonymousEnabled]
public ActionResult PublicAction()
{
}
}
[AnonymousEnabled]
public class ExplicitlyPublicController : ProtectedController
{
// inherits additional behaviors, but anonymous is enabled by attribute
}
public class PublicByOmissionController : Controller
{
// doesn't inherit and is thus public -- assuming whole site is open
}
public class AnonymousEnabledAttribute : Attribute
{
}
public class OverridableAuthorizeAttribute : AuthorizeAttribute
{
public override void OnAuthorization( AuthorizationContext context )
{
context.HttpContext.Items["ActionDescriptor"] = context.ActionDescriptor;
base.OnAuthorize( context );
}
public override bool AuthorizeCore( HttpContextBase context )
{
var actionDescriptor = context.Items["ActionDescriptor"] as ActionDescriptor;
if (actionDescriptor == null)
{
throw InvalidOperationException( "ActionDescriptor missing from context" );
}
var attribute = actionDescriptor
.GetCustomAttributes( typeof(AnonymousEnabledAttribute,true)
.FirstOrDefault();
if (attribute == null)
{
return base.AuthorizeCore( context );
}
return true;
}
}
Upvotes: 3
Reputation: 156469
You can create a location in your web.config file for the controllers that you want to always allow:
<configuration>
<system.web>
...
<authorization>
<deny users="?" />
</authorization>
</system.web>
...
<location path="MyArea/MyController">
<system.web>
<authorization>
<allow users="*" />
</authorization>
</system.web>
</location>
...
</configuration>
Upvotes: 1