如何使用 asp.net MVC 隐藏淘汰赛组件中基于角色的部分

Sim*_*ert 5 javascript asp.net asp.net-mvc razor knockout-3.0

防止用户在淘汰组件中看到诸如管理链接之类的内容的最佳方法是什么?

如果用户有权查看这些链接,我不想发出客户端请求,因为这会在客户端上公开此部分。

我能弄清楚的唯一方法是使用视图来表示组件模板,然后在渲染HTML之前检查用户是否在服务器端正确。

但是还有其他方法比这更干净吗?或者这是正确的方法吗?

Dav*_*ich 3

我在 AngularJS 应用程序中也遇到过类似的挑战。

我不想执行额外的服务请求,而是喜欢在 Model 或ViewBag.

为了简单起见,我们假设我们正在使用ViewBag.

1)操作方法中,设置

ViewBag.loggedIn = User.Identity.IsAuthenticated;
ViewBag.userId = User.Identity.GetUserId();

var identity = (System.Security.Claims.ClaimsIdentity)User.Identity;
ViewBag.roles = identity.Claims
                .Where(c => c.Type == ClaimTypes.Role)
                .Select(c => c.Value);
Run Code Online (Sandbox Code Playgroud)

2)JS 文件中,全局定义UserModel绑定和函数来检查用户是否具有正确的角色名称:

var UserModel = function () {
    var self = this;
    self.isLoggedIn = ko.observable("");
    self.userId = ko.observable("");
    self.roles = ko.observableArray([]);


    // function to check if role passed is in array
    self.hasRole = function (roleName) {

      for (i = 0; 1 < self.roles.length ; i++ ) {
          if (self.roles[i] == roleName)
             return true
      }
      return false;
    }

};

var UserData = new UserModel();
Run Code Online (Sandbox Code Playgroud)

在 .cshtml 视图中:

3)绑定角色和登录数据

<script type="text/javascript">
   UserData.isLoggedIn("@ViewBag.isLoggedIn");
   UserData.userId("@ViewBag.userId");
   UserData.roles(@Html.Raw(Json.Encode(ViewBag.roles));
</script>
Run Code Online (Sandbox Code Playgroud)

4)Role如果正确则显示部分:

<div data-bind="visible: UserData.hasRole("Admin")>
          ....
</div>
Run Code Online (Sandbox Code Playgroud)

隐藏管理组件的方法:

剃刀方式:

除了使用Knockout隐藏组件之外,还有C#/Razor方法

-> 嵌套 if 子句

@((List<String>) ViewBag.roles.contains("Admin")) 
{

...

}
Run Code Online (Sandbox Code Playgroud)

Razor Conditions 相对于Knockout的优点是,当服务器创建页面时,组件不会渲染,不会留下任何痕迹让客户端看到

-> 中的条件部分_Layout

@if ((List<String>) ViewBag.roles.contains("Admin"))
{
    @RenderSection("Admin Section")
}
Run Code Online (Sandbox Code Playgroud)

比简单的 Razor Condition 更干净,并在整个应用过程中自动应用

-> 部分儿童动作

称为(Action, Controller, Parameter)

@Html.Action("AdminConsole", "Admin", new { Role = "Admin"})

public ActionResult AdminComponent(string Role)
        {

            If (List<String>) ViewBag.roles.contains("Admin")
                  return PartialView(
            return View(products);
        }
Run Code Online (Sandbox Code Playgroud)

所有方法中最干净的。可以合并在一个部分中以获得更大的便利。


关于如何隐藏管理组件的结论:

您选择如何隐藏管理组件取决于您的需要。Razor /C#方法更方便并且感觉更安全。

另一方面,如果您有兴趣为用户提供SPA体验,C#那么服务器方法就不够了。您是否允许用户在不刷新页面的情况下进行身份验证?如果是这样,管理员可以进行身份​​验证并从匿名用户更改为管理员。

如果您愿意刷新屏幕以显示更改的内容,C#/Razor这就是您的方法。如果您的首要任务是为用户提供“响应式体验”,您将需要实施Knockout解决方案。