首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >“安全意识”动作链接?

“安全意识”动作链接?
EN

Stack Overflow用户
提问于 2010-04-27 14:08:04
回答 4查看 5K关注 0票数 21

如何创建“安全感知”操作链接,以检测用户是否有权单击(调用)该操作?

如果不允许用户使用该操作,请隐藏链接.

依赖于

  • web.config (授权)和
  • 授权操作

上的属性

PS

我想在MVC中混合这2是不好的做法吧?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2010-04-27 14:26:20

这是从MvcSitemap项目中盗取的一些代码,并对其进行了修改以供我自己使用。如果我没记错的话,这段代码已经为MVC2做了修改,有些函数可能不得不移植回MVC1。

将MVC和FormsAuthentication混合在一起的做法一点也不坏,MVC的默认身份验证方法是围绕现有的Asp.net安全基础设施构建的。

确定用户是否具有权限的代码:

代码语言:javascript
复制
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助手

代码语言:javascript
复制
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()的调用永远不会返回操作描述符

我试图找出这个问题,但没能解决,最后我做了一件工作。:(

票数 30
EN

Stack Overflow用户

发布于 2012-12-26 20:14:14

jfar的代码在很大程度上对我有用,但我不得不对MVC4做一些修改。这是唯一需要改变的方法:

代码语言:javascript
复制
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, actionDescriptor);

    // run each auth filter until on fails
    // performance could be improved by some caching
    foreach (var filter in FilterProviders.Providers.GetFilters(controllerContext, actionDescriptor))
    {
        var authFilter = filter.Instance as IAuthorizationFilter;

        if (authFilter == null)
            continue;

        authFilter.OnAuthorization(authContext);

        if (authContext.Result != null)
            return false;
    }

    return true;
}
票数 7
EN

Stack Overflow用户

发布于 2012-03-22 09:07:10

区域部分比仅仅添加一些过载要复杂一些。UseNamespaceFallback黑客不起作用,因为当您在不同区域具有相同名称的控制器时,您将实例化错误。

您需要有一种方法为该区域获取正确的命名空间。

否则这个

代码语言:javascript
复制
 IController controller = factory.CreateController(helper.ViewContext.RequestContext, controllerName); 

会出错的。

目前,我在视图中有这样的链接

代码语言:javascript
复制
@Html.SecurityTrimmedActionLink("this link", "Index", "Home",new {Area=string.Empty});   
@Html.SecurityTrimmedActionLink("this link", "Index", "FunctionAdministration", new   {Area="Administration" }, null);

内部

代码语言:javascript
复制
public static bool HasActionPermission(this HtmlHelper htmlHelper, string actionName, string controllerName, object area)

当area为空时,我将获得该区域的名称空间或默认名称空间。

代码语言:javascript
复制
private static string GetNamespaceForArea(string area, RouteCollection routeColl)
    {
        string ns = string.Empty;
        foreach (RouteBase routeBase in routeColl)
        {
            if (routeBase.GetType() == (typeof (Route)))
            {
                Route route = (Route) routeBase;
                RouteValueDictionary dataTokens = route.DataTokens;
                ;
                if (area != null)
                {
                    if (dataTokens.ContainsKey("area"))
                    {
                        if (area.Equals(dataTokens["area"]))
                        {
                            ns = (string) ((string[]) dataTokens["Namespaces"])[0];
                            break;
                        }
                    }
                    else
                    {
                        if (area.Equals(string.Empty))
                        {
                            ns = (string) ((string[]) dataTokens["Namespaces"])[0];
                            break;
                        }
                    }
                }
            }
        }
        return ns;
    }

您需要在您的路由中以globalasax设置默认名称空间,例如如下(默认ns "ActionLinkTest.Controllers"):

代码语言:javascript
复制
routes.MapRoute(
            "Default", // Route name
            "{controller}/{action}/{id}", // URL with parameters
            new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
            , new[] { "ActionLinkTest.Controllers" }
        );

使用它创建基于类型名称的控制器:

代码语言:javascript
复制
ControllerBase controllerToLinkTo = string.IsNullOrEmpty(controllerName) ? htmlHelper.ViewContext.Controller :(ControllerBase) Activator.CreateInstance(Type.GetType(type));

在global.asax中定义区域

代码语言:javascript
复制
areaRegistration.Add("Administration","Areas.Administration");
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2721869

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档