Đây là một số mã được săn bắt từ dự án MvcSitemap và được sửa đổi để tôi sử dụng. Nếu tôi nhớ chính xác mã này đã được sửa đổi cho MVC2 và một số chức năng có thể phải được chuyển về MVC1.
Thực tiễn không tồi của nó để kết hợp MVC và FormsAuthentication cùng nhau, phương pháp xác thực mặc định của MVC được xây dựng xung quanh cơ sở hạ tầng bảo mật Asp.net hiện có.
Mã để xác định xem người dùng có quyền truy cập:
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 Helpers
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("");
}
}
Cảnh báo: Điều này sẽ không làm việc trong MVC 5 vì cuộc gọi đến FindAction() không bao giờ trả về một bộ mô tả hành động
Tôi đã cố gắng tìm ra vấn đề và không thể và kết thúc lập trình một công việc xung quanh. :(
Tôi đã kết hợp mã @ jfar với MvcSiteMapProvider để cung cấp hỗ trợ cho Khu vực. Nếu bất cứ ai quan tâm, tôi đã đặt những gì tôi có trên CodePlex tại https://authorizedactionlink.codeplex.com/. Nguồn và nhị phân .NET Framework 4.0 DLL có sẵn trên đó. – Bitmapped