“安全意识"动作链接? [英] "Security aware" action link?
问题描述
如何创建安全感知"操作链接以检测用户是否有权单击(调用)操作?
如果不允许用户使用该操作,则隐藏链接...
How can I create a "security aware" action link that detects if a user is authorized to click (invoke) the action?
Hide link if user is not allowed to use that action...
取决于
- web.config(授权)和
- [授权] 操作的属性
PS
我想在 MVC 中混合这两个是不好的做法?
PS
I guess it is bad practice to mix those 2 in MVC?
推荐答案
这是从 MvcSitemap 项目中挖出并修改为我自己使用的一些代码.如果我没记错的话,此代码已针对 MVC2 进行了修改,并且某些功能可能必须向后移植到 MVC1.
This is some code poached from the MvcSitemap project and modified for my own use. If I remember correctly this code has been modified for MVC2 and some of the functions might have to be back ported to MVC1.
将 MVC 和 FormsAuthentication 混合在一起完全不是坏习惯,MVC 的默认身份验证方法是围绕现有的 Asp.net 安全基础架构构建的.
Its not bad practices at all to mix MVC and FormsAuthentication together, MVC's default authentication methods are build around the existing Asp.net security infrastructure.
用于确定用户是否具有权限的代码:
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("");
}
}
警告:这在 MVC 5 中不起作用,因为对 FindAction() 的调用从不返回动作描述符
我试图找到问题,但无法解决,最终编写了一个变通方法.:(
I tried to find the issue and couldn't and ended up programming a work around. :(
这篇关于“安全意识"动作链接?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!