【问题标题】:Authorization in ASP.net5ASP.net5 中的授权
【发布时间】:2016-05-06 19:26:29
【问题描述】:

我正在尝试查看 ASP.net5 中是否有“开箱即用”的东西来授权我的应用程序需求。我正在使用基于组/权限的方法进行授权。使用 Identity3 我使用角色作为组,然后我从中创建了权限。每个权限都有一个链接到的资源和 1 个或多个值,例如:

资源 = 页面,权限 = 添加、更新、查看、删除

另一个复杂之处是组具有动态名称和动态权限!!

我已经开始阅读 ASP.net5 中的授权,并且似乎找到了一个叫做 Policies 的东西,听起来不错。这似乎迫使您使用 Claims,如果我使用 ClaimsTransformer 来获取我的所有权限并将它们添加为来自 Db 的声明,这是可能的。但是我是否认为我必须为每个权限、每个资源创建一个策略?这似乎是很多设置。

有什么我不知道的东西已经内置在 ASP.net5 中我可以使用吗?像这样的属性

[Authorize("Page", "Delete")]

我可以添加到 PageController Delete 方法中。

如果我必须在控制器中使用某种服务和 DI 来实现这一点,那也可以。

【问题讨论】:

  • 在 asp.net 中。除了位置和文件夹结构之外,它们没有任何变化,是的,一些新的东西,如启动、cs 文件,但 mvc 工作流程中的核心功能没有任何变化。所以请再次查看所有代码和参考。如果一切正常,它将起作用。

标签: c# asp.net asp.net-mvc asp.net-core asp.net-core-mvc


【解决方案1】:

有一个ClaimsPrincipalPermissionAttribute 可以满足您的要求。

或者你可以实现自己的AuthorizeAttribute

【讨论】:

  • ClaimsPrincipalPermission 在 aspnet 5 中不可用
  • 您不能在 asp.net 核心中实现自己的 AuthorizeAttribute。该属性不包含代码。
【解决方案2】:

我使用AspNet.Security.OpenIdConnect.Server 进行授权。不过你也可以看看OpenIddict

在任何情况下,您都可以像这样将 Authorize 属性添加到您想要的任何方法中

[Authorize(Roles = "Administrator,SimpleUser,AnOtherRole")]
public void MyMethod() {}

【讨论】:

  • 组和权限是动态的,所以这不起作用
  • 你总是可以创建一个自定义的 Authorize 属性并在那里做任何你想做的事情
【解决方案3】:

Resource based authorization 可能会满足您的需求,但我对作为资源的页面而不是页面的作用有点困惑。

采用您的页面/删除组合,我想您的页面删除操作不是页面资源,而是一个参数,指示要删除的页面? (如果不是这种情况,那么这种方法当然行不通)

在这种情况下,你会做类似的事情

[Authorize]
public class PageController : Controller
{
    IAuthorizationService _authorizationService;

    public PageController(IAuthorizationService authorizationService)
    {
        _authorizationService = authorizationService;
    }

    public Delete(int pageId)
    {
        var page = pageRepo.GetPage(pageId);
        if (await authorizationService.AuthorizeAsync(User, page,  Operations.Delete))
        {
            return View(page);
        }
        else
        {
            return new ChallengeResult();
        }
    }
}

为了实现这一点,您需要根据页面和操作要求(或任何旧要求,但参数化操作要求意味着您可以编写单个处理程序并相应地分支)编写处理程序。

我们非常努力地不再将数据放入属性中,而是将其转移到需求中,因为坦率地说,属性中的数据是维护的噩梦。

还有一点需要注意;由于处理程序是通过 DI 解析的,因此您可以将您的用户注入到处理程序中的权限解析器中,这将避免使用声明转换。

【讨论】:

  • 也许“页面”是个坏名字,但那是我的对象的名称。所以这是在 PageController 中(可以称为公司、联系人或其他名称)。我不需要针对模型进行验证,但我确实需要检查用户是否具有权限(我想我可以只是交换页面以获得权限?)。这可以使用这种方法来完成吗,因为我更喜欢使用属性。还有Operations.Delete是什么?
  • 首先点击答案开头的链接。这就是运营。
  • 第二 - 您检查哪些不需要实例的资源和权限?添加新的“公司”?对公司的编辑权限需要公司本身。如果它是添加的,那么您可以走资源路线并传入一个新的 Company(),或者您有类似 CompanyPermission 声明之类的东西,并将 CRUD 类型权限放入其中,然后在公司控制器上使用声明检查策略而不是检查用户是否有任何公司访问权限,然后深入了解每个控制器方法
【解决方案4】:

ASP.NET 提供了易于使用的开箱即用的身份验证机制,例如:

public class HomeController : Controller
{
    [Authorize]
    public ActionResult Index()
    {
        ViewBag.Message = "This can be viewed only by authenticated users only";
        return View();
    }

    [Authorize(Roles="admin")]
    public ActionResult AdminIndex()
    {
        ViewBag.Message = "This can be viewed only by users in Admin role only";
        return View();
    }
}

查看this tutorial

或者,如果您想要更复杂的机制,您可以基于 ASP.NET Membership Provider 实现自己的 memberhsip 提供程序

【讨论】:

  • 这与 asp.net5 无关,角色(组)也是动态的
  • 这是 .net 网络应用程序框架的一部分,您可以将它与任何 .net 版本一起使用,更重要的是,我向您保证它可以满足您最初在问题中提出的要求。
  • @Fourat 不,没有。如果角色是动态的,则不符合问题的要求。您已硬编码 admin 角色以访问 AdminIndex。这不是动态的。
  • @mason 请阅读教程,Authorize 属性接受一个 Roles 参数,它是一个字符串,您可以对该字符串进行硬编码,从 XML 中获取它,将其加载到可枚举中,从数据库中获取。 .. 这取决于你。
  • 您尚未在答案中展示如何使其动态化。我也不相信内置属性可以做到这一点。你会得到一个错误:An attribute argument must be a constant expression, typeof expression, or array creation expression of an attribute parameter type.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-11-21
  • 1970-01-01
  • 2012-05-31
  • 2011-08-05
  • 2016-05-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多