Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net mvc 基于控制器/动作授权属性的MVC用户界面修剪_Asp.net Mvc_User Interface_Authorization - Fatal编程技术网

Asp.net mvc 基于控制器/动作授权属性的MVC用户界面修剪

Asp.net mvc 基于控制器/动作授权属性的MVC用户界面修剪,asp.net-mvc,user-interface,authorization,Asp.net Mvc,User Interface,Authorization,我有一个安全的应用程序,每个操作都有一个Authorize属性 [Authorize(Roles = "Role1,Role2")] public ActionResult MyAction(int id) { return View(); } 在我的UI中,我有指向这些控制器/操作的链接。我想为接受控制器和操作名称的链接创建自定义HtmlHelper: @Html.SecuredLink("Click Me", "MyAction", "MyController"); 这将根据用户

我有一个安全的应用程序,每个操作都有一个
Authorize
属性

[Authorize(Roles = "Role1,Role2")]
public ActionResult MyAction(int id)
{
    return View();
}
在我的UI中,我有指向这些控制器/操作的链接。我想为接受控制器和操作名称的链接创建自定义HtmlHelper:

@Html.SecuredLink("Click Me", "MyAction", "MyController");
这将根据用户是否具有给定操作的权限来决定是否渲染天气:

public static MvcHtmlString SecuredLink(this HtmlHelper helper, string text, string action, string controller)
{        
    var userId = Membership.GetUserId();

    var userHasRightsToThisAction = IsActionAccessibleToUser(helper.ViewContext.RequestContext.HttpContext, controller, action); // <- How would this work?

    if (userHasRightsToThisAction )
    {
       // Render Link
       // ...
    }
}
public static MvcHtmlString SecuredLink(此HtmlHelper帮助程序、字符串文本、字符串操作、字符串控制器)
{        
var userId=Membership.GetUserId();

var userHasRightsToThisAction=IsActionAccessibleToUser(helper.ViewContext.RequestContext.HttpContext,controller,action);//Ok,quick and Dirth解决方案:

准备用于构建URL服务器端的函数

这样的东西可能是最好的选择:

public static string GetUrl(string Action, string Controller, object RouteValues) {
    UrlHelper Url = new UrlHelper(HttpContext.Current.Request.RequestContext);
    return Url.Action(Action, Controller, RouteValues);
}
在帮助程序中,获取用户身份验证信息并返回生成的url或string.Empty

public static string SecureLink(this HtmlHelper helper, string Action, string Controller, object RouteValues)
{
  YourUserObject LoggedUser = /* Whatever you need to obtain your UserId */
  if (LoggedUser.IsSuperUser) {
    return GetUrl(Action, Controller, RouteValues);
  }
  return string.empty;
}
如果结果是HTML编码的,只需使用MvcHtmlString代替string作为返回值。 否则,您可能需要使用
@Html.Raw
来发出它


PS:显然,我没有在这个示例代码中添加完整的
生成,这取决于您决定需要哪些参数(将它们添加到助手签名中),我通常复制其他
@Html
助手的签名(因此名称、值和一个HtmlAttributes列表).

确定找到了一个解决方案。在深入研究了MvcSiteMap之后,我发现了这篇关于它的文章:

我使用了这段代码的一部分,稍作修改,创建了一个方法,它可以提供我想要的结果:

    /// <summary>
    /// Determine if a controller/action is accessible for a user
    /// </summary>
    /// <param name="context">Current HttpContext</param>
    /// <param name="controllerName">Target controller</param>
    /// <param name="actionName">Target action</param>
    /// <returns>True/false if the action is accessible</returns>
    public static bool IsActionAccessibleToUser(HttpContextBase context, string controllerName, string actionName)
    {
        // Find current handler
        MvcHandler handler = context.Handler as MvcHandler;

        if (handler != null)
        {
            // try to figure out the controller class
            IController controller = null;
            try
            {
                controller = ControllerBuilder.Current.GetControllerFactory().CreateController(handler.RequestContext, controllerName);                    
            }
            catch (System.Web.HttpException e)
            {
                throw new Exception("The controller '" + controllerName + "Controller' was not found.", e);
            }

            // Find all AuthorizeAttributes on the controller class and action method
            object[] controllerAttributes = controller.GetType().GetCustomAttributes(typeof(AuthorizeAttribute), true);
            object[] actionAttributes = controller.GetType().GetMethod(actionName).GetCustomAttributes(typeof(AuthorizeAttribute), true);

            // No attributes, then the action is open to all
            if (controllerAttributes.Length == 0 && actionAttributes.Length == 0) return true;

            // Find out current principal
            IPrincipal principal = handler.RequestContext.HttpContext.User;

            // Do we pass the roles for the controller?
            string roles = "";
            if (controllerAttributes.Length > 0)
            {
                AuthorizeAttribute attribute = controllerAttributes[0] as AuthorizeAttribute;
                roles = attribute.Roles;

                if (!PassRoleValidation(principal, roles)) return false;
            }

            // Do we pass the roles for the action?
            if (actionAttributes.Length > 0)
            {
                AuthorizeAttribute attribute = actionAttributes[0] as AuthorizeAttribute;
                roles = attribute.Roles;

                if (!PassRoleValidation(principal, roles)) return false;
            }

            return true;
        }

        return false;
    }

    private static bool PassRoleValidation(IPrincipal principal, string roles)
    {
        // no roles, then all we need to be is authenticated
        if (string.IsNullOrEmpty(roles) && principal.Identity.IsAuthenticated) return true;

        string[] roleArray = roles.Split(',');

        // if role contains "*", it's open to all
        if (roleArray.Any(role => role == "*")) return true;

        // Determine if the current user is allowed to access the current node
        if (roleArray.Any(principal.IsInRole)) return true;

        return false;
    }
//
///确定用户是否可以访问控制器/操作
/// 
///当前HttpContext
///目标控制器
///目标行动
///如果操作可访问,则为True/false
公共静态bool IsActionAccessibleToUser(HttpContextBase上下文、字符串控制器名、字符串操作名)
{
//查找当前处理程序
MvcHandler handler=context.handler作为MvcHandler;
if(处理程序!=null)
{
//尝试找出控制器类
i控制器控制器=空;
尝试
{
controller=ControllerBuilder.Current.GetControllerFactory().CreateController(handler.RequestContext,controllerName);
}
catch(System.Web.httpe异常)
{
抛出新异常(“未找到控制器“+”控制器名称“+”控制器“”,e);
}
//查找控制器类和操作方法上的所有属性
object[]controllerAttributes=controller.GetType().GetCustomAttributes(typeof(AuthorizeAttribute),true);
object[]actionAttributes=controller.GetType().GetMethod(actionName).GetCustomAttributes(typeof(AuthorizeAttribute),true);
//没有属性,则该操作对所有人开放
if(controllerAttributes.Length==0&&actionAttributes.Length==0)返回true;
//找出当前负责人
IPrincipal principal=handler.RequestContext.HttpContext.User;
//我们是否传递控制器的角色?
字符串角色=”;
如果(controllerAttributes.Length>0)
{
AuthorizeAttribute=controllerAttributes[0]作为AuthorizeAttribute;
角色=属性。角色;
如果(!PassRoleValidation(主体、角色))返回false;
}
//我们是否传递动作的角色?
如果(actionAttributes.Length>0)
{
AuthorizeAttribute=actionAttributes[0]作为AuthorizeAttribute;
角色=属性。角色;
如果(!PassRoleValidation(主体、角色))返回false;
}
返回true;
}
返回false;
}
私有静态布尔传递(IPrincipal主体,字符串角色)
{
//没有角色,那么我们需要的只是身份验证
if(string.IsNullOrEmpty(roles)和&principal.Identity.IsAuthenticated)返回true;
字符串[]rolarray=roles.Split(',');
//如果角色包含“*”,则对所有人开放
if(rolarray.Any(role=>role==“*”)返回true;
//确定是否允许当前用户访问当前节点
if(rolarray.Any(principal.IsInRole))返回true;
返回false;
}

您能否澄清为什么无法正常呈现链接,然后在自定义AuthorizeAttribute中重定向?不过,我认为您应该先查看用户。Identity对象具有授权名称,然后您可以决定呈现。我不希望用户在无权访问该链接所引导的页面时能够单击该链接s到。当您说“LoggedUser.issupurer”时,我想根据每个MVC操作的授权解码来确定权限。这是我正在努力解决的部分。因此,如果操作具有“Authorize(Roles=“Associate”),我想以某种方式确定这一点,并让系统告诉我当前用户是否是“Associate”“,或者更好的是,他们是否有资格执行该操作。我真诚地怀疑您是否可以从帮助程序访问属性属性,该帮助程序是在执行该操作后为呈现视图而执行的。您可以尝试构建javascript(客户端)启用/禁用链接的工件,但这将使属性装饰无效。在这种情况下,IMHO最好让链接可点击并处理未授权的服务器端。好的,我正在测试不同的控制器/操作,而不是相同的。因此我在a/B上,链接转到a/C,所以我想问a/C用户是否有权访问好了。所以我不想测试我在里面的控制器/动作。如果你的控制器有两个,这是行不通的