gpt4 book ai didi

java - 如何将 JAAS 授权检查委托(delegate)给 Shiro?

转载 作者:行者123 更新时间:2023-12-02 14:05:23 27 4
gpt4 key购买 nike

我正在开发一个需要基于对象的身份验证和授权的服务器端应用程序。我喜欢 Shiro 的简单,但是为了兼容 JAAS,我写了一个 LoginModule,它使用 Apache Shiro 作为底层机制。

但我的问题是我找不到将 JAAS 授权检查委托(delegate)给 Shiro 的方法。我怎样才能做到这一点?

最佳答案

注意:答案解决了通过标准安全框架将外部授权系统与 JVM 集成的一般情况。它不是特定于 Shiro 或 JMX 的,因为我对它们都不熟悉。

从概念上讲,您似乎是在策略决策点 (PDP) 之后——即评估授权查询(“实体 X 是否允许执行 Y?”)的设施。 JDK 提供了以下几种:

  • 有效 SecurityManager ,特别是它的 checkXXX方法组。
  • ProtectionDomain 类,尤其是它的 implies(Permission)方法。
  • key implies(ProtectionDomain, Permission)有效的方法 Policy .
  • 其次,implies CodeSource 的方法, PermissionCollection , Permission , 和 Principal .

  • 任何上述方法都可以被覆盖,以便以递增的粒度定制概念 PDP 的功能。应该指出的是,JAAS 确实(与其名称所暗示的相反)并没有真正带来自己的 PDP;相反,它提供了 means除了代码来源的原始信任因素之外,域和策略支持基于主体的查询。因此,在我看来,您对保持“JAAS 兼容”的要求基本上意味着想要使用(原始加 JAAS)Java SE 授权模型,也就是沙箱,我怀疑这是否是您想要的。当标准模型被认为太低级和/或性能密集型时,往往会采用像 Shiro 这样的框架;换句话说,当授权逻辑不需要为一组给定的信任因素评估每个单独的堆栈帧时,因为这些因素更频繁地与上下文无关。根据我的假设的有效性,出现三种主要情况需要检查:
  • 授权是AccessControlContext -独立的。 Shiro 本地授权属性 (SNAA),无论它们是什么,都适用于整个线程。代码来源无关紧要。
  • 代码来源很重要,强制使用沙箱。 SNAAs 仍然是 AccessControlContext -独立的。
  • 代码来源和 SNAA 都相关且 AccessControlContext -依赖。

  • 1. 仅基于 SNAA 的授权
  • 以您认为合适的方式管理身份验证。如果您想继续使用 JAAS' javax.security.auth用于认证的SPI,忘记建立标准Subject作为认证结果,而不是直接将 Shiro 特定的绑定(bind)到线程本地存储。这样您就可以更方便地访问 SNAA,而不必使用 AccessControlContext (并遭受潜在的 performance penalty ),以进行检索。
  • 子类 SecurityManager ,至少覆盖两个 checkPermission方法,使他们
  • 如有必要,翻译 Permission
  • 之前,将争论转化为 Shiro 的 PDP (SPDP) 理解的东西
  • 将线程本地 SNAA 和权限委托(delegate)给 SPDP(如果 SPDP 发出信号访问拒绝,则抛出 SecurityException)。

  • 安全上下文接收重载可以简单地忽略相应的参数。在应用程序初始化时,实例化并安装 ( System::setSecurityManager ) 您的实现。

    2. 混合授权,结合代码来源和上下文不敏感的 SNAA
  • 以您认为合适的方式管理身份验证;再次联想到Shiro专用Subject与线程本身。
  • 子类 SecurityManager ,至少覆盖两个 checkPermission方法,这一次,它们委托(delegate)给 SPDP 和/或覆盖的实现(相应地,在当前或提供的访问控制上下文上调用 checkPermission)。对于任何给定的许可,应该咨询哪个(哪些)和以什么顺序当然取决于实现。当两者都被调用时,应该首先查询 SPDP,因为它可能比访问控制上下文响应得更快。
  • 如果 SPDP 要额外处理授予来自特定位置和/或代码签名者集的代码的权限评估,您还必须将 Policy 子类化。 , 实现 implies(ProtectionDomain, Permission)这样,比如 SecurityManager::checkPermission上面,它将域的一些可理解的表示(通常只有它的 CodeSource)和权限参数——但逻辑上不是 SNAA——传递给 SPDP。实现应该尽可能高效,因为它将在每个域每个访问控制上下文中调用一次 checkPermission。时间。实例化并安装 ( Policy::setPolicy ) 您的实现。

  • 3.混合授权,结合代码源和SNAA,两者都上下文敏感
  • 以您认为合适的方式管理身份验证。不幸的是,主题处理部分并不像创建 ThreadLocal 那样微不足道。在这种情况下。
  • 子类化、实例化并安装 Policy执行 SecurityManager::checkPermission 的组合职责和 Policy::implies ,如在第二种情况中单独描述的那样。
  • 实例化并安装标准 SecurityManager .
  • 创建一个 ProtectionDomain子类,能够存储和暴露 SNAA。
  • 作者 1 DomainCombiner
  • 是用 SNAA 构建的;
  • 工具combine(ProtectionDomain[], ProtectionDomain[])以至于
  • 它用自定义实现的等效实例替换第一个(“当前”上下文)数组参数的域;
  • 然后将第二个(“分配的”或“继承的”上下文)参数的参数(如果有)按原样附加到前者;最后
  • 返回串联。


  • Policy::implies ,实现应该是高效的(例如,通过消除重复项),因为它会在每次 getContext 时被调用。和 checkPermission AccessController方法是。
  • 身份验证成功后,创建一个新的 AccessControlContext包装当前的,以及自定义 DomainCombiner 的一个实例,依次包装 SNAA。包装要执行的代码
    那个点“内”AccessController::doPrivilegedWithCombiner调用,还传递替换访问控制上下文。

  • 1 除了使用自定义域和您自己的组合器实现之外,还有一种看似更简单的替代方法,将 SNAA 转换为 Principal s 和,使用标准 SubjectDomainCombiner ,将它们绑定(bind)到当前 AccessControlContext的域(如上,或只是通过 Subject::doAs )。这种方法是否会降低策略的效率主要取决于调用堆栈的深度(访问控制上下文包含多少个不同的域)。最终,您认为可以避免作为域组合器的一部分实现的缓存优化将在编写策略时回击您,因此这实际上是您在那时必须做出的设计决策。

    关于java - 如何将 JAAS 授权检查委托(delegate)给 Shiro?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5736077/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com