如何使用 asp.net MVC 在挖空组件中隐藏基于角色的部分
How to hide role based section in knockout component using asp.net MVC
防止用户在 knockout 组件中看到类似 admin 链接 的最佳方法是什么?
如果用户有权查看这些链接,我不想发出客户端请求,因为这会在客户端公开此部分。
我能弄清楚的唯一方法是使用视图来表示组件模板,然后在呈现 HTML[ 之前检查用户是否在服务器端正确=23=].
但是有没有比这更干净的另一种方法,或者这是正确的方法吗?
我在 AngularJS 应用程序方面遇到过类似的挑战。
与其执行额外的服务请求,我更喜欢在模型或 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);
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 Conditions 相对于 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
是您的方法。如果您的首要任务是为用户提供 "responsive experience",您将需要实施 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...
};
}
我知道在提供您寻求的要求的同时没有更简洁的方法来做到这一点。
防止用户在 knockout 组件中看到类似 admin 链接 的最佳方法是什么?
如果用户有权查看这些链接,我不想发出客户端请求,因为这会在客户端公开此部分。
我能弄清楚的唯一方法是使用视图来表示组件模板,然后在呈现 HTML[ 之前检查用户是否在服务器端正确=23=].
但是有没有比这更干净的另一种方法,或者这是正确的方法吗?
我在 AngularJS 应用程序方面遇到过类似的挑战。
与其执行额外的服务请求,我更喜欢在模型或 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);
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 Conditions 相对于 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
是您的方法。如果您的首要任务是为用户提供 "responsive experience",您将需要实施 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...
};
}
我知道在提供您寻求的要求的同时没有更简洁的方法来做到这一点。