ASP.NET MVC - Easy way to temporarily require authorisation for whole site except one page
I am building a site with a mixture of public and member-only pages. The login system works fine as it is.
However I'd like to launch a closed, invite-only preview and temporarily require visitors log in for all actions except the welcome page.
Currently I have [Authorize]
attributes on certain action methods. I could add additional attributes to the other action methods too, but this feels a bit hacky and will make it harder开发者_如何学编程 to remove them correctly later when I want to revert to having more open content.
So, how can I effectively add a site-wide authorisation requirement? Recall that I want the single /Home/Index
route to remain public as well, so that people I've invited can read some information before activating their invites.
I think doing this in the web.config
file would be the best since it is temporary and will not require that you add any C#
code or rely on roles/names etc.
Do the following in your web.config
<configuration>
<!-- system.web is the only already in your web.config
don't add this, just add the authorization element
to the existing system.web element -->
<system.web>
<authorization>
<deny users="?"/>
</authorization>
</system.web>
<!-- the login path -->
<location path="Login/Index">
<system.web>
<authorization>
<allow users="?"/>
</authorization>
</system.web>
</location>
<!-- welcome page -->
<location path="Home/Index">
<system.web>
<authorization>
<allow users="?"/>
</authorization>
</system.web>
</location>
<!-- static files (images, css, js etc.) folder -->
<location path="Content">
<system.web>
<authorization>
<allow users="?"/>
</authorization>
</system.web>
</location>
</configuration>
The first <authorization>
element will restrict access to your application to only authenticated/logged in users. The subsequent <location>
elements place exceptions on specific paths (login page, welcome screen and static files).
Make sure you verify that the path
attribute is correct for each location based on your application.
Some more details on the location
element can be found at MSDN 'location element'.
Add a custom filter - here's my implementation for a similar requirement. The main difference from what you describe is that it requires a role set from the invite page rather than letting in any logged in user.
public class PreviewAuthAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext);
// if site is live, show page
if (Data.Settings.IsLive) return;
// if request is from localhost or build server, show page
if (filterContext.HttpContext.Request.IsLocal) return;
if (filterContext.HttpContext.Request.UserHostAddress.StartsWith("192.168.0")) return;
// if user has has alpha or admin role, show page
if (filterContext.HttpContext.Request.IsAuthenticated && (filterContext.HttpContext.User.IsInRole("Alpha") || filterContext.HttpContext.User.IsInRole("Admin"))) return;
// site is not live and user does not have access - show placeholder
filterContext.Result = new ViewResult()
{
ViewName="Placeholder",
ViewData = filterContext.Controller.ViewData,
TempData = filterContext.Controller.TempData
};
}
}
You could customize the Authorize attribute and have your list of users for private beta need to pass some logic within. Just remove the customization when you go public.
Stack Overflow answer on how to customize the Authorize attribute
Look at the answer containing AuthorizeOwnerAttribute too.
精彩评论