简体   繁体   English

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

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

What is the best way to prevent user from seeing things like admin links in a knockout component? 什么是阻止用户在淘汰组件中看到管理员链接等内容的最佳方法?

I don't want to make a client request if the user has right to see those links because it would expose this section on the client. 如果用户有权查看这些链接,我不想发出客户端请求,因为它会在客户端上公开此部分。

The only way I can figure it out is to use a view to represent the component template and then check if the user as right on the server-side before rendering the HTML . 我能弄清楚的唯一方法是使用视图来表示组件模板,然后在呈现HTML之前检查用户是否在服务器端是正确的。

But is there another way that can be cleaner than this or is it the right way to proceed? 但是,还有另一种比这更清洁的方式,还是正确的方法?

I've faced similar challenges with AngularJS Apps. 我在AngularJS Apps上面临着类似的挑战。

Rather than perform an extra service request, I like to pass logged-in status and role in Model or ViewBag . 我喜欢在Model或ViewBag传递登录状态和角色,而不是执行额外的服务请求。

For simplicity, let's assume we're using ViewBag . 为简单起见,我们假设我们正在使用ViewBag

1) In the Action Method , set 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) In a JS File , globally define UserModel with bindings and function to check if user has correct role-name: 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();

In .cshtml View: 在.cshtml中查看:

3) bind Role and Logged in data 3)绑定角色并登录数据

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

4) Show Partial if Role is correct: 4)如果Role正确则显示部分:

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

Ways to hide Admin Components: 隐藏管理组件的方法:

The Razor Ways: 剃刀方式:

Rather than hide components with Knockout , there are C#/Razor ways 而不是使用Knockout隐藏组件,而是有C#/ Razor方式

-> Nested if clause - >嵌套if子句

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

...

}

The advantage of Razor Conditions over Knockout is the component will not render when server creates page, leaving no trace for client to see Razor条件优于Knockout的优点是当服务器创建页面时组件不会呈现,不会留下客户端看到的痕迹

-> Conditional sections in _Layout - > _Layout条件部分

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

Cleaner than simple Razor Condition and automatically applied throughout application 比简单的Razor Condition更清洁,并在整个应用程序中自动应用

-> Partial with Child Action - >部分与儿童行动

Called (Action, Controller, Parameter) : 调用(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);
        }

The cleanest of all approaches. 所有方法中最干净的。 Can be combined in a section for greater convenience. 可以在一个部分组合以获得更大的便利。


Conclusion on how to hide Admin Components: 关于如何隐藏管理组件的结论:

How you choose to hide Admin Components depends on your needs. 您如何选择隐藏管理组件取决于您的需求。 The Razor/C# approach is more convenient and feels more secure. Razor / C#方法更方便,更安全。

On the other hand, if you are interested in giving the user the SPA experience, C# and server methods fall short. 另一方面,如果您有兴趣为用户提供SPA体验,那么C#和服务器方法就会失败。 Do you allow users to Authenticate without refreshing pages? 您是否允许用户进行身份验证而不刷新页面? If so, an Admin may Authenticate and change from anonymous user to Admin. 如果是这样,管理员可以验证并从匿名用户更改为管理员。

If you are comfortable with refreshing the screen to show the changed content, C#/Razor is your approach. 如果您对刷新屏幕以显示更改的内容感到满意,那么C#/Razor就是您的方法。 If your priority is to give the user the "responsive experience", You will want to implement a Knockout solution. 如果您的首要任务是为用户提供“响应体验”,那么您需要实现Knockout解决方案。

If you cannot expose the markup to the client, then the only way to do this would be on the server before the markup is generated. 如果您无法将标记公开给客户端,那么执行此操作的唯一方法是在生成标记之前在服务器上。 As you have pointed out, this would be done in the view rendering. 正如您所指出的,这将在视图渲染中完成。

In your case, using a partial view to hold your KO component would be appropriate and provide the functionality that you need while allowing you to reuse the component markup. 在您的情况下,使用部分视图来保存您的KO组件是合适的,并提供您需要的功能,同时允许您重用组件标记。

Here is the method I have used in the past, which has worked very cleanly: 这是我过去使用的方法,它非常干净地工作:

View 视图

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

Additional context could even be passed to the partial view via the MVC view model if necessary. 如有必要,甚至可以通过MVC视图模型将附加上下文传递给局部视图。

Component Partial View 组件部分视图

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

Component View Model 组件视图模型

function FooComponentViewModel(params) {
    var self = this;

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

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

I know of no cleaner way to do this while providing the requirements that you seek. 我知道在提供您所寻求的要求的同时,没有更清洁的方法。

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

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