如何实现安全修剪的Html.RenderAction?

时间:2012-11-20 10:03:01

标签: asp.net-mvc asp.net-mvc-3

我希望创建一个安全修剪(基本上如果你没有权限不渲染)Html.RenderAction。

目的是显示各种小部件/页面组件,如果此人没有对该操作的权限,则不会调用RenderAction(或者至少不会导致重定向到登录页面)。例如,该页面将显示给所有登录用户。但是,会有部分仅用于人力资源,业务开发,如果您从事人力资源和业务开发,您将获得这两个部分等。

RenderAction调用的每个部分都是独立的,这意味着我可以轻松地创建包含所有必需部分的页面,但是如果不允许用户则不会显示它们。如果我为某个动作调用RenderAction而某人没有权限,则会导致他们重新定向到登录页面。

我已经看到类似的链接,但任何人都做了类似的动作?

我希望得到类似的东西:

@Html.RenderSecurityTrimmedAction("Main","Business-Widget1")
@Html.RenderSecurityTrimmedAction("Main","HR-Widget")
@Html.RenderSecurityTrimmedAction("Main","General-Widget3")

Widget访问权限基于人员当前角色。我的安全访问工作完美。它主要是创建一个RenderAction,如果用户没有perission,它就不会不经常地运行Action

我想保留代码DRY,所以我不想携带大量的ViewModel属性,然后必须将每个Html.RenderAction包装在if语句中。这些组件将出现在各种各样的地方,所以我希望它们即插即用。

4 个答案:

答案 0 :(得分:3)

您可以尝试使用此扩展方法:

public static void CustomRenderAction(this HtmlHelper helper, string actionName)
{
    if (helper.ViewContext.HttpContext.User.Identity.IsAuthenticated == false)
        return;

    helper.RenderAction(actionName);
}

如果你想为每个动作指定角色,你可以做下一件事:

1)覆盖AuthorizeAttribute,如下所示:

public class MyAuthAttribute: AuthorizeAttribute
{
  public override void OnAuthorization(AuthorizationContext filterContext)
  {
    if (filterContext.HttpContext.Items["DontRedirectToLogin"] != null)
    {
       if (base.AuthorizeCore(filterContext.HttpContext) == false)
       {
          filterContext.Result = new EmptyResult();
          return;
       }

       return;
    }

    base.OnAuthorization(filterContext);
  }
}

2)更改RenderAction:

public static void CustomRenderAction(this HtmlHelper helper, string actionName)
{
    helper.ViewContext.HttpContext.Items["DontRedirectToLogin"] = true

    helper.RenderAction(actionName);
}

答案 1 :(得分:1)

有多种用户类型和权限或访问权限因用户类型而异。

这是我从你的问题中得到的。根据权限,您需要显示或隐藏组件。组件可以是页面中的网格,按钮,文本框,消息等。 或者根据登录用户(他的权限)以不同方式呈现视图。

使用HTML Helper可以轻松实现。

一个粗略的想法。

您需要将数据存储在xml,数据库等中。即,您需要使用控制器和操作映射登录的用户类型。

表/数据权限设置

Admin - UserController- ViewAllUsersAction
Admin-  UserController- DeleteUserAction
Employee - UserController- RequestUserAccessAction
Employee - AlertsController- LatestNewsAction
* - UsersController- ChangePasswordAction

考虑两种用户类型。管理员,员工。管理员可以访问ViewAllUsers,DeleteUser等。员工可以访问ReqUserAccess,LatestNewsAction。

<强>的HtmlHelper

public static bool IsAuthorized(this HtmlHelper helper, string Controller, string Action)
{ 
   // This method query the database/storage withe controller,action and usertype.
   // In case of WindowsAuthentication, you can get the userGroup from a LDAP Server/Domain. You must know the logged in user group here, if you are not using win auth.
}

在EmpList.Cshtml中

if( @Html.IsAuthorized("UserController","DeleteUserAction"))   <input type="submit" text="Delete Employee" />

因此,如果用户类型是Admin,那么它将返回true else,false,因此该部分不会被执行而不会显示。

如果是Windows身份验证,我们需要使用Windows用户组而不是上面提到的usertype。

修改

if( @Html.IsAuthorized("Main","HR-Widget"))
   @Html.RenderSecurityTrimmedAction("Main","HR-Widget") 
   // this will be rendered only based on the permission for the user.

谢谢,希望这对你有用。 :)

答案 2 :(得分:0)

我发现这里的扩展方法效果最好:http://vivien-chevallier.com/Articles/create-an-authorized-action-link-extension-for-aspnet-mvc-3

它实际上会对您指定的操作执行所有ActionFilters,因此您不必自己执行它。

唯一的缺点是它不支持区域的编写方式。我确信它可以被修改以理解区域。

答案 3 :(得分:0)

我实施了以下内容:

    public static void SecurityTrimmedRenderAction(this HtmlHelper htmlHelper,
                                                  ActionResult actionResult)
    {
        var routeValueDictionary = actionResult.GetRouteValueDictionary();
        var actionName = (string)routeValueDictionary["Action"];
        var controllerName = (string)routeValueDictionary["Controller"];
        //var areaName = (string)routeValueDictionary["Area"];
        var hasActionPermission = SecurityTrimmingExtensions.HasActionPermission(htmlHelper, actionName,
                                                                                 controllerName);
        if (hasActionPermission)
        {
            htmlHelper.RenderAction(actionResult);
        }
    }

SecurityTrimmingExtensions遵循此处的代码:ASP.Net MVC how to determine if a user can access a URL?

我不必触摸授权这样做,因为如果当前用户没有权限则不会调用代码