坚持创建与QUOT;安全修整" html.ActionLink扩展方法 [英] Stuck creating a "security trimmed" html.ActionLink extension method

查看:186
本文介绍了坚持创建与QUOT;安全修整" html.ActionLink扩展方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图创建一个扩展方法对MVC的的HtmlHelper。
其目的是启用或禁用基础上,AuthorizeAttribute在控制器/动作设置ActionLink的。
从<借款href=\"http://blog.maartenballiauw.be/post/2008/08/29/Building-an-ASPNET-MVC-sitemap-provider-with-security-trimming.aspx\"相对=nofollow> MVCSitemap

这马腾Balliauw创建code,我想在决定如何渲染ActionLink的前验证用户对控制器/操作的权限。
当我试图让MvcHandler,我得到一个空值。
有没有更好的方式来为控制器/动作的属性?

下面是code的扩展方法:

 公共静态类HtmlHelperExtensions
{
    公共静态字符串SecurityTrimmedActionLink(此的HtmlHelper的HtmlHelper,LINKTEXT串,串动,串控制器)
    {
        //简化为简洁
        如果(IsAccessibleToUser(动作,控制器))
        {
            返回htmlHelper.ActionLink(LINKTEXT,动作,控制器);
        }
        其他
        {
            返回的String.Format(&LT;跨度&GT; {0}&LT; / SPAN&gt;中,LINKTEXT);
        }
    }    公共静态布尔IsAccessibleToUser(串动,串控制器)
    {
        HttpContext的背景下= HttpContext.Current;        MvcHandler处理器= context.Handler为MvcHandler;        一个IController verifyController =
            ControllerBuilder类
            。当前
            .GetControllerFactory()
            .CreateController(handler.RequestContext,控制器);        [对象] controllerAttributes = verifyController.GetType()GetCustomAttributes(typeof运算(AuthorizeAttribute),TRUE)。
        [对象] actionAttributes = verifyController.GetType()实现getMethod(动作).GetCustomAttributes(typeof运算(AuthorizeAttribute),TRUE)。        如果(controllerAttributes.Length == 0安培;&安培; actionAttributes.Length == 0)
            返回true;        主要的IPrincipal = handler.RequestContext.HttpContext.User;        串角色=;
        字符串用户=;
        如果(controllerAttributes.Length大于0)
        {
            AuthorizeAttribute属性= controllerAttributes [0]作为AuthorizeAttribute;
            角色+ = attribute.Roles;
            用户+ = attribute.Users;
        }
        如果(actionAttributes.Length大于0)
        {
            AuthorizeAttribute属性= actionAttributes [0]作为AuthorizeAttribute;
            角色+ = attribute.Roles;
            用户+ = attribute.Users;
        }        如果(string.IsNullOrEmpty(角色)及&放大器; string.IsNullOrEmpty(用户)及&放大器; principal.Identity.IsAuthenticated)
            返回true;        串[] roleArray = roles.Split(,);
        串[] usersArray = users.Split(,);
        的foreach(在roleArray串角色)
        {
            如果(角色=*&放大器;!&安培;!principal.IsInRole(角色))返回false;
        }
        的foreach(在usersArray字符串用户)
        {
            如果(用户=*&放大器;!及(principal.Identity.Name ==|| principal.Identity.Name =用户)!)返回false;
        }
        返回true;
    }}


解决方案

下面是工作code:

 使用系统;
使用System.Collections.Generic;
使用System.Linq的;
使用的System.Web;
使用System.Security.Principal;
使用System.Web.Routing;
使用System.Web.Mvc;
System.Collections中使用;
使用的System.Reflection;
命名空间System.Web.Mvc.Html
{
    公共静态类HtmlHelperExtensions
    {
        公共静态字符串SecurityTrimmedActionLink(
        这个的HtmlHelper的HtmlHelper,
        串LINKTEXT,
        串动,
        串控制器)
        {
            返回SecurityTrimmedActionLink(的HtmlHelper,LINKTEXT,动作,控制器,FALSE);
        }
        公共静态字符串SecurityTrimmedActionLink(此的HtmlHelper的HtmlHelper,LINKTEXT串,串动,串控制器,布尔showDisabled)
        {
            如果(IsAccessibleToUser(动作,控制器))
            {
                返回htmlHelper.ActionLink(LINKTEXT,动作,控制器);
            }
            其他
            {
                返回showDisabled?的String.Format(&LT;跨度&GT; {0}&LT; / SPAN&gt;中,LINKTEXT):;
            }
        }
        公共静态布尔IsAccessibleToUser(字符串actionAuthorize,串controllerAuthorize)
        {
            装配装配= Assembly.GetExecutingAssembly();
            GetControllerType(controllerAuthorize);
            键入controllerType = GetControllerType(controllerAuthorize);
            VAR控制器=(一个IController)Activator.CreateInstance(controllerType);
            ArrayList的controllerAttributes =新的ArrayList(controller.GetType()GetCustomAttributes(typeof运算(AuthorizeAttribute),真));
            ArrayList的actionAttributes =新的ArrayList();
            MethodInfo的[] =方法controller.GetType()的getMethods()。
            的foreach(在方法MethodInfo的方法)
            {
                [对象]属性= method.GetCustomAttributes(typeof运算(ActionNameAttribute),TRUE);
                如果((attributes.Length == 0安培;&安培; method.Name == actionAuthorize)||(attributes.Length大于0和放大器;及((ActionNameAttribute)属性[0])名称== actionAuthorize)。)
                {
                    actionAttributes.AddRange(method.GetCustomAttributes(typeof运算(AuthorizeAttribute),真));
                }
            }
            如果(controllerAttributes.Count == 0安培;&安培; actionAttributes.Count == 0)
                返回true;            主要的IPrincipal = HttpContext.Current.User;
            串角色=;
            字符串用户=;
            如果(controllerAttributes.Count大于0)
            {
                AuthorizeAttribute属性= controllerAttributes [0]作为AuthorizeAttribute;
                角色+ = attribute.Roles;
                用户+ = attribute.Users;
            }
            如果(actionAttributes.Count大于0)
            {
                AuthorizeAttribute属性= actionAttributes [0]作为AuthorizeAttribute;
                角色+ = attribute.Roles;
                用户+ = attribute.Users;
            }            如果(string.IsNullOrEmpty(角色)及&放大器; string.IsNullOrEmpty(用户)及&放大器; principal.Identity.IsAuthenticated)
                返回true;            串[] roleArray = roles.Split(,);
            串[] usersArray = users.Split(,);
            的foreach(在roleArray串角色)
            {
                如果(角色==*|| principal.IsInRole(角色))
                    返回true;
            }
            的foreach(在usersArray字符串用户)
            {
                如果(用户==*&放大器;及(principal.Identity.Name ==用户))
                    返回true;
            }
            返回false;
        }        公共静态类型GetControllerType(字符串controllerName)
        {
            装配装配= Assembly.GetExecutingAssembly();
            的foreach(在assembly.GetTypes类型类型())
            {
                如果(type.BaseType.Name ==控制器和放大器;及(type.Name.ToUpper()==(controllerName.ToUpper()+控制器.ToUpper())))
                {
                    返回类型;
                }
            }
            返回null;
        }
    }
}

我不喜欢使用反射,但我不能获取到ControllerTypeCache。

I'm trying to create an Extension Method for MVC's htmlHelper. The purpose is to enable or disable an ActionLink based on the AuthorizeAttribute set on the controller/action. Borrowing from the MVCSitemap
code that Maarten Balliauw created, I wanted to validate the user's permissions against the controller/action before deciding how to render the actionlink. When I try to get the MvcHandler, I get a null value. Is there a better way to the the attributes for the controller/action?

Here is the code for the extension method:

public static class HtmlHelperExtensions
{
    public static string SecurityTrimmedActionLink(this HtmlHelper htmlHelper, string linkText, string action, string controller)
    {
        //simplified for brevity 
        if (IsAccessibleToUser(action, controller))
        {
            return htmlHelper.ActionLink(linkText, action,controller);    
        }
        else
        {
            return String.Format("<span>{0}</span>",linkText);    
        }
    }

    public static bool IsAccessibleToUser(string action, string controller)
    {
        HttpContext context = HttpContext.Current;

        MvcHandler handler = context.Handler as MvcHandler;            

        IController verifyController = 
            ControllerBuilder
            .Current
            .GetControllerFactory()
            .CreateController(handler.RequestContext, controller);

        object[] controllerAttributes = verifyController.GetType().GetCustomAttributes(typeof(AuthorizeAttribute), true);
        object[] actionAttributes = verifyController.GetType().GetMethod(action).GetCustomAttributes(typeof(AuthorizeAttribute), true);

        if (controllerAttributes.Length == 0 && actionAttributes.Length == 0)
            return true;

        IPrincipal principal = handler.RequestContext.HttpContext.User;

        string roles = "";
        string users = "";
        if (controllerAttributes.Length > 0)
        {
            AuthorizeAttribute attribute = controllerAttributes[0] as AuthorizeAttribute;
            roles += attribute.Roles;
            users += attribute.Users;
        }
        if (actionAttributes.Length > 0)
        {
            AuthorizeAttribute attribute = actionAttributes[0] as AuthorizeAttribute;
            roles += attribute.Roles;
            users += attribute.Users;
        }

        if (string.IsNullOrEmpty(roles) && string.IsNullOrEmpty(users) && principal.Identity.IsAuthenticated)
            return true;

        string[] roleArray = roles.Split(',');
        string[] usersArray = users.Split(',');
        foreach (string role in roleArray)
        {
            if (role != "*" && !principal.IsInRole(role)) return false;
        }
        foreach (string user in usersArray)
        {
            if (user != "*" && (principal.Identity.Name == "" || principal.Identity.Name != user)) return false;
        }
        return true;
    }

}

解决方案

Here is the working code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Security.Principal;
using System.Web.Routing;
using System.Web.Mvc;
using System.Collections;
using System.Reflection;
namespace System.Web.Mvc.Html
{
    public static class HtmlHelperExtensions
    {
        public static string SecurityTrimmedActionLink(
        this HtmlHelper htmlHelper,
        string linkText,
        string action,
        string controller)
        {
            return SecurityTrimmedActionLink(htmlHelper, linkText, action, controller, false);
        }
        public static string SecurityTrimmedActionLink(this HtmlHelper htmlHelper, string linkText, string action, string controller, bool showDisabled)
        {
            if (IsAccessibleToUser(action, controller))
            {
                return htmlHelper.ActionLink(linkText, action, controller);
            }
            else
            {
                return showDisabled ? String.Format("<span>{0}</span>", linkText) : "";
            }
        }
        public static bool IsAccessibleToUser(string actionAuthorize, string controllerAuthorize)
        {
            Assembly assembly = Assembly.GetExecutingAssembly();
            GetControllerType(controllerAuthorize);
            Type controllerType = GetControllerType(controllerAuthorize);
            var controller = (IController)Activator.CreateInstance(controllerType);
            ArrayList controllerAttributes = new ArrayList(controller.GetType().GetCustomAttributes(typeof(AuthorizeAttribute), true));
            ArrayList actionAttributes = new ArrayList();
            MethodInfo[] methods = controller.GetType().GetMethods();
            foreach (MethodInfo method in methods)
            {
                object[] attributes = method.GetCustomAttributes(typeof(ActionNameAttribute), true);
                if ((attributes.Length == 0 && method.Name == actionAuthorize) || (attributes.Length > 0 && ((ActionNameAttribute)attributes[0]).Name == actionAuthorize))
                {
                    actionAttributes.AddRange(method.GetCustomAttributes(typeof(AuthorizeAttribute), true));
                }
            }
            if (controllerAttributes.Count == 0 && actionAttributes.Count == 0)
                return true;

            IPrincipal principal = HttpContext.Current.User;
            string roles = "";
            string users = "";
            if (controllerAttributes.Count > 0)
            {
                AuthorizeAttribute attribute = controllerAttributes[0] as AuthorizeAttribute;
                roles += attribute.Roles;
                users += attribute.Users;
            }
            if (actionAttributes.Count > 0)
            {
                AuthorizeAttribute attribute = actionAttributes[0] as AuthorizeAttribute;
                roles += attribute.Roles;
                users += attribute.Users;
            }

            if (string.IsNullOrEmpty(roles) && string.IsNullOrEmpty(users) && principal.Identity.IsAuthenticated)
                return true;

            string[] roleArray = roles.Split(',');
            string[] usersArray = users.Split(',');
            foreach (string role in roleArray)
            {
                if (role == "*" || principal.IsInRole(role))
                    return true;
            }
            foreach (string user in usersArray)
            {
                if (user == "*" && (principal.Identity.Name == user))
                    return true;
            }
            return false;
        }

        public static Type GetControllerType(string controllerName)
        {
            Assembly assembly = Assembly.GetExecutingAssembly();
            foreach (Type type in assembly.GetTypes())
            {
                if (type.BaseType.Name == "Controller" && (type.Name.ToUpper() == (controllerName.ToUpper() + "Controller".ToUpper())))
                {
                    return type;
                }
            }
            return null;
        }
    }
}

I don't like using reflection, but I can't get to the ControllerTypeCache.

这篇关于坚持创建与QUOT;安全修整&QUOT; html.ActionLink扩展方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆