卡住创建“安全修剪”html.ActionLink 扩展方法

2023-11-30

我正在尝试为 MVC 的 htmlHelper 创建一个扩展方法。 目的是根据控制器/操作上设置的 AuthorizeAttribute 启用或禁用 ActionLink。 借自MVC站点地​​图
在 Maarten Balliauw 创建的代码中,我想在决定如何呈现操作链接之前验证用户对控制器/操作的权限。 当我尝试获取 MvcHandler 时,我得到一个 null 值。 有没有更好的方法来获取控制器/操作的属性?

这是扩展方法的代码:

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;
    }

}

这是工作代码:

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;
        }
    }
}

我不喜欢使用反射,但我无法访问 ControllerTypeCache。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

卡住创建“安全修剪”html.ActionLink 扩展方法 的相关文章

随机推荐

  • 根据 2 个以上组的百分比随机分配对照组与治疗组

    小猪放弃了我之前的问题python pandas 根据 随机分配对照组与治疗组 感谢 maxU 我知道如何将随机对照组 治疗组分配为 2 个组 但如果我有 3 个或更多组怎么办 例如 df head customer id Group ma
  • 如何用python3生成unicode字符串

    我用过这个 u unicode text utf 8 但是使用 Python 3 时出现错误 或者 也许我只是忘记包含一些内容 NameError global name unicode is not defined 谢谢 Python3
  • 从字符串中提取可变长度的数量

    我想从字符串中提取多个可变长度 该字符串如下所示 used memory 1775220696 我想要1775220696变量中的一部分 对此有很多疑问 但我找不到适合我需要的解决方案 您可以使用cut my val echo used m
  • 从 Java 应用程序启动 OpenVPN [关闭]

    Closed 这个问题需要多问focused 目前不接受答案 是否可以通过 Java 应用程序启动 OpenVPN 如果可能的话 最好的方法是什么 这样它是跨平台的 并且可以在所有安装了 OpenVPN 的平台上运行 你可以像这样用 Jav
  • 在构造函数或类中的粗箭头中绑定

    所以我想知道这之间是否有区别 import React Component PropTypes from react class Example extends Component constructor props super props
  • 仅将函数应用于一个 div 类,而不是全部

    我目前正在网站上的位置页面上工作 并且在显示 隐藏 jquery 效果时遇到问题 下面的 jQuery 激活点击并应用切换 div 的类以显示 隐藏它 非常简单 但是 当我添加更多具有相同类的 div 并单击激活器链接时 它会在所有 div
  • 在某些行/列值处提取子矩阵

    我需要根据行 列索引和切片距离来切片 2D 输入数组 在下面的示例中 我可以从输入矩阵中提取 3x3 子矩阵 但我无法调整此代码以适应我想要的任何搜索距离 而无需手动写下索引 Example import numpy as np creat
  • 寻找具有分段完成/树模型的 QCompleter 示例

    PySide 文档包含此部分具有树模型的 QCompleter PySide QtGui QCompleter 可以在树模型中查找补全 假设任何项目 或子项目或子子项目 都可以通过指定项目的路径明确表示为字符串 然后一次完成一层 让我们以用
  • 为什么有时在 Windows 控制台程序中按 Ctrl+Z 时才会终止输入? [复制]

    这个问题在这里已经有答案了 我知道使用 ctrl z 来表示 EOF 或 EOT 通常已经过时且不推荐 但我只是好奇幕后发生了什么 假设我在 C 中有这样的东西 include
  • Angular 通用参考错误 - KeyboardEvent 未定义

    我在其中添加了 多米诺骨牌 服务器 ts甚至还更新了webpack server config js as module rules test ts js loader regexp replace loader options match
  • 是否可以使用 Streams.intRange 函数?

    我想使用 Streams intRange int start int end int step 来实现反向排序流 然而 似乎 java util Streams 类不再可用 但它仍然在标准库的 rt jar 中 该方法是否在其他类中或被其
  • 修改ggplot中的viridis调色板

    我试图通过一个主要是数字的因素来为 ggplot 着色 如下所示 iris gt ggplot aes Sepal Length Sepal Width color cut Petal Length 0 7 geom point scale
  • Angular 2 共享服务将数据传递到组件

    我正在尝试传递字符串值this title从我的登陆页面 组件到我的结果页面 组件 我检索到list show值 并将其发送到我的TitleService就像我的 登陆页面 component html ol li list show li
  • 正则表达式仅匹配整个单词中的数字

    我想使用 NET 匹配字符串内的正数和负数 无小数或千位分隔符 但我只想匹配整个单词 所以如果一个字符串看起来像 redeem 1234 paid 234432 那么我想匹配 1234 和 234432 但如果文本是 LS022 1234
  • VB.NET 中的 HTTP GET

    在 VB net 中发出 http get 的最佳方法是什么 我想得到像这样的请求的结果http api hostip info ip 68 180 206 184 在 VB NET 中 Dim webClient As New Syste
  • 使用 youtube API v3 时订单不起作用

    我正在尝试获取某个频道的最后 10 个视频 当我运行以下代码时 from apiclient discovery import build API SERVICE NAME youtube API VERSION v3 def youtub
  • “警告:在参数列表中声明了‘结构矩阵’[默认启用]”和错误:‘scanToken’的类型冲突

    我一直在研究这个问题 试图找出导致这些错误的原因 但到目前为止我一无所获 我有这个功能 struct token scanToken struct matrix refTable struct token send int counter
  • 如何自动重新启动 CSS 动画

    我是网页设计新手 在 CSS 方面面临一些问题 其实我是在克隆amazon com并创建一个带有滑动动画的滑块 但动画只运行一次 我想让它无限运行 这是我的代码 HTML index html
  • 请推荐最佳的批量删除选项

    我正在使用 PostgreSQL 8 1 4 我有 3 个表 一个是核心表 表 1 其他是从属表 表 2 表 3 我在表1中插入了70000条记录 并在其他2个表中插入了适当的相关记录 由于我使用了 CASCADE 我可以使用 DELETE
  • 卡住创建“安全修剪”html.ActionLink 扩展方法

    我正在尝试为 MVC 的 htmlHelper 创建一个扩展方法 目的是根据控制器 操作上设置的 AuthorizeAttribute 启用或禁用 ActionLink 借自MVC站点地 图在 Maarten Balliauw 创建的代码中