问题
I chose to do a school project with asp.net mvc3 and there is a need of a user/role management. I think the membership that ships with asp.net is way too big for a school projec.
SO my thought is this. if i could find an equivalent of Zend predispatch
method for asp or even a better one i could store the urls accessible as privilege for a role and load it in session and check if a particular user have access to it and redirect if not.
my question are this:
Is there any equivalent of PreDispatch
method in asp?
Is there any better approach for my problem ? if yes please post resources
Thanks for reading this
EDIT i generate sublinks from databse using this:
public static class SubMenuHelper
{
public static MvcHtmlString GetSubMenu()
{
var db = new SchoolContextExpress();
var submenu = from s in db.Disciplines select s;
var sbuilder = new StringBuilder();
foreach (var discipline in submenu)
{
sbuilder.AppendFormat("<li><a class='sublink' href='/Discipline/Details/{0}'>{1}</a></li>", discipline.DisciplineID, discipline.Name);
}
return new MvcHtmlString(sbuilder.ToString());
}
}
回答1:
You can implement like this.
- Enum for roles
- FilterAttribute
- Create Web.sitemap for menu
- Add Menu creator action
- Add Menu to _Layout.cshtml
- Add FilterAttribute to controller or action
----1 Enum------
public enum Roles{
Common=1,
Student = 2,
Teacher=4
Administration=8
}
----2 RequirePermissionFilter----
public class RequirePermissionFilter : ActionFilterAttribute, IAuthorizationFilter
{
private readonly Roles[] _requiredRoles;
public RequirePermissionFilter(Roles requiredRoles)
{
_requiredRoles = new Roles[] { requiredRoles };
}
public RequirePermissionFilter(Roles[] requiredRoles)
{
_requiredRoles = requiredRoles;
}
public void OnAuthorization(AuthorizationContext filterContext)
{
var success = false;
foreach (Roles role in _requiredRoles)
{
success |= _authManager.HasPermission(role);
}
if (success)
{
var cache = filterContext.HttpContext.Response.Cache;
cache.SetProxyMaxAge(new TimeSpan(0));
cache.AddValidationCallback((HttpContext context, object data, ref HttpValidationStatus validationStatus) =>
{
validationStatus = this.OnCacheAuthorization(new HttpContextWrapper(context));
}, null);
}
else
{
this.HandleUnauthorizedRequest(filterContext);
}
}
private void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
// Ajax requests will return status code 500 because we don't want to return the result of the
// redirect to the login page.
if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest())
{
filterContext.Result = new HttpStatusCodeResult(500);
}
else
{
filterContext.Result = new RedirectToRouteResult("Error - 401", null);
}
}
public HttpValidationStatus OnCacheAuthorization(HttpContextBase httpContext)
{
var success = false;
foreach (Roles role in _requiredRoles)
{
success |= _authManager.HasPermission(role);
}
if (success)
{
return HttpValidationStatus.Valid;
}
else
{
return HttpValidationStatus.IgnoreThisRequest;
}
}
}
----3 Web.sitemap-----
<?xml version="1.0" encoding="utf-8" ?>
<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >
<siteMapNode url="" roleName="" title="" menuVisible="True">
<siteMapNode url="~/Home/Index" roleName="-1" title="Home" menuVisible="True"/>
<siteMapNode url="~/Student/Index" roleName="2 title="Student" menuVisible="True">
<siteMapNode url="~/MyLessons/Index" roleName="2 title="My Lessons" menuVisible="True"/>
</siteMapNode>
<siteMapNode url="~/Teacher/Index" roleName="4 title="Teacher" menuVisible="True"/>
<siteMapNode url="~/Administration/Index" roleName="8 title="Administration" menuVisible="True"/>
</siteMapNode>
</siteMap>
----4 Menu Creator Action----
public class CommonController : Controller{
public ActionResult NavigationMenu()
{
return Content(SiteMapMenu());
}
public string SiteMapMenu()
{
StringBuilder sb = new StringBuilder();
sb.Append("<div class='menu'><ul>");
var topLevelNodes = SiteMap.RootNode.ChildNodes;
foreach (SiteMapNode node in topLevelNodes)
{
if (HasPermission(node) && IsVisible(node))
{
if (SiteMap.CurrentNode == node)
sb.Append("<li class='selectedMenuItem'>");
else
sb.Append("<li>");
if (!string.IsNullOrEmpty(node.Url))
sb.AppendFormat("<a href='{0}'>{1}</a>", Url.Content(node.Url), node.Title);
else
sb.AppendFormat("<a href='javascript:void(0)'>{0}</a>", node.Title);
if (node.HasChildNodes && AnyOfChildIsVisible(node))
{
foreach (SiteMapNode childNode in node.ChildNodes)
{
if (HasPermission(childNode) && IsVisible(childNode))
{
sb.Append("<li>");
sb.AppendFormat("<a href='{0}'>{1}</a>", Url.Content(childNode.Url), childNode.Title);
sb.Append("</li>");
}
}
sb.Append("</ul></div>");
}
sb.AppendLine("</li>");
}
}
sb.AppendLine("</ul></div>");
return sb.ToString();
}
private bool HasPermission(SiteMapNode node)
{
int roleName = int.Parse(node["roleName"].ToString());
if ((roleName == -1) || (_authManager.HasPermission((Roles)roleName)))
return true;
return false;
}
private bool IsVisible(SiteMapNode node)
{
return bool.Parse(node["menuVisible"]);
}
private bool AnyOfChildIsVisible(SiteMapNode node)
{
foreach (SiteMapNode item in node.ChildNodes)
{
if (IsVisible(item))
return true;
}
return false;
}
}
----5 Add helper to _Layout.cshtml
@Html.Action("NavigationMenu", "Common")
----6 Controller----
[RequirePermissionFilter(Roles.Student)]
public class StudentController : Controller{
/*
*
*
*
*
*/
}
----AuthManager---
public interface IAuthManager
{
bool HasPermission(Roles requiredRole);
}
public class AuthManager : IAuthManager
{
private ISessionManager _sessionManager;
private ISuggestionConfig _config;
public bool HasPermission(Roles requiredRoles)
{
if (HttpContext.Current.Session["USER"] != null)
return (requiredRoles & ((User)HttpContext.Current.Session["USER"]).Roles) == requiredRoles;
else
return false;
}
}
来源:https://stackoverflow.com/questions/9479005/tiny-custom-role-management-for-asp-net-mvc-3