昨天遇到一个有趣的问题。只有我的身份1的mvc网站我使用IPrincipal
扩展方法进行自定义身份验证,这在所有需要它的剃刀视图中都能正常工作。现在使用Identity 2,我需要通过扩展方法访问ApplicationUserManager
,因此我被迫从所有视图中传递HttpContext.Current
。
除了内部剃刀@section
部分之外,这种方法很好 - 在调用堆栈之后,看起来这些不会被渲染,直到控制器被处理完毕,这将处理我的数据库和用户管理器等
围绕此限制的最佳方法是什么?我想继续使用部分,因为它们让我轻松地在html的底部注入javascript,但我也想在这些部分中继续使用razor扩展,因为它们是一种非常好的,简单的方法来控制输出到页。
目前我被迫创建一个新的ApplicationUserManager
和MyDbContext
,将它们填入ViewBag
,然后将它们传递给扩展程序,这不是&# 39;理想。
我的扩展方法示例:
public static bool HasPermission(this IPrincipal source, ApplicationUserManager um, MyDbContext db, string controller, string method) {
if (!source.Identity.IsAuthenticated) {
return false;
}
var roles = um.GetRoles(source.Identity.GetUserId());
if (roles.Count == 0) {
return false;
}
// Admins have global access
string role = roles[0];
if (role.Equals("Admin")) {
return true;
}
// This is fine being un-domained, permissions are global
PermissionMatrix permission = db.PermissionMatrices.FirstOrDefault(x => x.Controller == controller && x.Action == method && x.RoleName == role);
return permission != null;
}
使用地点的示例:
@if (User.HasPermission((ApplicationUserManager)ViewBag.UserManager, (MyDbContext)ViewBag.Database, "Event", "Create")) {
@Html.ActionLink("Create New", "Create")
}
编辑以使问题本身更清晰:
这是我放入黑客之前的扩展方法 -
public static bool HasPermission(this IPrincipal source, HttpContext context, string controller, string method) {
var userManager = context.GetOwinContext().Get<ApplicationUserManager>();
var myDb = context.GetOwinContext().Get<MyDbContext>();
就像我上面说的那样,这有效(从.cshtml页面传递HttpContext.Current),除非调用在剃刀@section
内,然后失败,因为这些在控制器之后运行处置完毕,将东西丢弃在OwinContext中。
上面的代码是我现在工作的hacky方式;在我的控制器中,我必须创建一个额外的MyDbContext和一个额外的ApplicationUserManager。