这是从MVCSitemap项目中提取的一些代码,并进行了修改以供我自己使用。如果我没记错的话,这个代码已经为MVC2修改过了,其中一些函数可能需要重新移植到MVC1。
将MVC和FormsAuthentication混合在一起是一种不错的做法,MVC的默认身份验证方法是围绕现有的ASP.NET安全基础结构构建的。
用于确定用户是否具有权限的代码:
public static class SecurityTrimmingExtensions
{
public static bool HasActionPermission( this HtmlHelper htmlHelper, string actionName, string controllerName )
{
//if the controller name is empty the ASP.NET convention is:
//"we are linking to a different controller
ControllerBase controllerToLinkTo = string.IsNullOrEmpty(controllerName)
? htmlHelper.ViewContext.Controller
: GetControllerByName(htmlHelper, controllerName);
var controllerContext = new ControllerContext(htmlHelper.ViewContext.RequestContext, controllerToLinkTo);
var controllerDescriptor = new ReflectedControllerDescriptor(controllerToLinkTo.GetType());
var actionDescriptor = controllerDescriptor.FindAction(controllerContext, actionName);
return ActionIsAuthorized(controllerContext, actionDescriptor);
}
private static bool ActionIsAuthorized(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
{
if (actionDescriptor == null)
return false; // action does not exist so say yes - should we authorise this?!
AuthorizationContext authContext = new AuthorizationContext(controllerContext);
// run each auth filter until on fails
// performance could be improved by some caching
foreach (IAuthorizationFilter authFilter in actionDescriptor.GetFilters().AuthorizationFilters)
{
authFilter.OnAuthorization(authContext);
if (authContext.Result != null)
return false;
}
return true;
}
private static ControllerBase GetControllerByName(HtmlHelper helper, string controllerName)
{
// Instantiate the controller and call Execute
IControllerFactory factory = ControllerBuilder.Current.GetControllerFactory();
IController controller = factory.CreateController(helper.ViewContext.RequestContext, controllerName);
if (controller == null)
{
throw new InvalidOperationException(
String.Format(
CultureInfo.CurrentUICulture,
"Controller factory {0} controller {1} returned null",
factory.GetType(),
controllerName));
}
return (ControllerBase)controller;
}
}
HTML帮助程序
public static class SecurityTrimmedLink
{
public static MvcHtmlString SecurityTrimmedActionLink(this HtmlHelper htmlHelper, string linkName, string actionName)
{
return htmlHelper.HasActionPermission(actionName, "")
? htmlHelper.ActionLink(linkName, actionName)
: MvcHtmlString.Create("");
}
public static MvcHtmlString SecurityTrimmedActionLink(this HtmlHelper htmlHelper, string linkName, string actionName, RouteValueDictionary routeValueDictionary )
{
return htmlHelper.HasActionPermission(actionName, "")
? htmlHelper.ActionLink(linkName, actionName, routeValueDictionary)
: MvcHtmlString.Create("");
}
public static MvcHtmlString SecurityTrimmedActionLink(this HtmlHelper htmlHelper, string linkName, string actionName, object routeValues, object htmlAttributes )
{
return htmlHelper.HasActionPermission(actionName, "")
? htmlHelper.ActionLink(linkName, actionName, routeValues, htmlAttributes)
: MvcHtmlString.Create("");
}
public static MvcHtmlString SecurityTrimmedActionLink(this HtmlHelper htmlHelper, string linkName, string actionName, string controllerName)
{
return htmlHelper.HasActionPermission(actionName, controllerName)
? htmlHelper.ActionLink(linkName, actionName, controllerName)
: MvcHtmlString.Create("");
}
public static MvcHtmlString SecurityTrimmedActionLink(this HtmlHelper htmlHelper, string linkName, string actionName, string controllerName, object routeValues, object htmlAttributes)
{
return htmlHelper.HasActionPermission(actionName, controllerName)
? htmlHelper.ActionLink(linkName, actionName, controllerName, routeValues, htmlAttributes)
: MvcHtmlString.Create("");
}
}
警告:这在MVC 5中不起作用,因为对findaction()的调用从不返回操作描述符
我试图找到这个问题,但却找不到,最后我编了一个解决方案。:(