繁体   English   中英

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

[英]How to hide role based section in knockout component using asp.net MVC

什么是阻止用户在淘汰组件中看到管理员链接等内容的最佳方法?

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

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

但是,还有另一种比这更清洁的方式,还是正确的方法?

我在AngularJS Apps上面临着类似的挑战。

我喜欢在Model或ViewBag传递登录状态和角色,而不是执行额外的服务请求。

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

1)Action Method中 ,设置

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

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();

在.cshtml中查看:

3)绑定角色并登录数据

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

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

<div data-bind="visible: UserData.hasRole("Admin")>
          ....
</div>

隐藏管理组件的方法:

剃刀方式:

而不是使用Knockout隐藏组件,而是有C#/ Razor方式

- >嵌套if子句

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

...

}

Razor条件优于Knockout的优点是当服务器创建页面时组件不会呈现,不会留下客户端看到的痕迹

- > _Layout条件部分

@if ((List<String>) ViewBag.roles.contains("Admin"))
{
    @RenderSection("Admin Section")
}

比简单的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);
        }

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


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

您如何选择隐藏管理组件取决于您的需求。 Razor / C#方法更方便,更安全。

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

如果您对刷新屏幕以显示更改的内容感到满意,那么C#/Razor就是您的方法。 如果您的首要任务是为用户提供“响应体验”,那么您需要实现Knockout解决方案。

如果您无法将标记公开给客户端,那么执行此操作的唯一方法是在生成标记之前在服务器上。 正如您所指出的,这将在视图渲染中完成。

在您的情况下,使用部分视图来保存您的KO组件是合适的,并提供您需要的功能,同时允许您重用组件标记。

这是我过去使用的方法,它非常干净地工作:

视图

<script type="text/javascript">
    ko.components.register("foo", {
        viewModel: FooComponentViewModel,
        template: { element: "component-foo" }
    });
</script>

...

<foo params="IsAdmin: @(User.IsInRole("Admin") ? 'true' : 'false')"></foo>

...

@Html.Partial("Components/_Foo")

如有必要,甚至可以通过MVC视图模型将附加上下文传递给局部视图。

组件部分视图

<template id="component-foo">
    @if(@User.IsInRole("Admin"))
    {
        // something you DO care about the client seeing
    }

    ...
</template>

@if(@User.IsInRole("Admin"))
{
    <script type="text/javascript">
        // Some JS code to hide from non admins for this component
    </script>
}

组件视图模型

function FooComponentViewModel(params) {
    var self = this;

    self.AdminDoSomething = function () {
        if (!params.IsAdmin) {
            return;
        }

        // something you DO NOT care about the client seeing...
    };
}

我知道在提供您所寻求的要求的同时,没有更清洁的方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM