如何将 JAAS 授权检查委托给 Shiro?
我正在开发一个服务器端应用程序,该应用程序需要基于对象进行身份验证和授权。我喜欢Shiro的简单性,但是为了与JAAS兼容,我写了一个使用Apache Shiro作为底层机制的LoginModule。
但我的问题是,我找不到将JAAS授权检查委托给Shiro的方法。我怎样才能做到这一点?
我正在开发一个服务器端应用程序,该应用程序需要基于对象进行身份验证和授权。我喜欢Shiro的简单性,但是为了与JAAS兼容,我写了一个使用Apache Shiro作为底层机制的LoginModule。
但我的问题是,我找不到将JAAS授权检查委托给Shiro的方法。我怎样才能做到这一点?
注意:答案解决了外部授权系统通过标准安全框架与JVM集成的一般情况。它不是特定于Shiro或JMX的,因为我对两者都不熟悉。
从概念上讲,您似乎在策略决策点 (PDP) 之后 - 即评估授权查询(“实体 X 是否允许执行 Y?”)的工具。JDK 提供了以下几个:
安全管理器
,特别是其方法组。checkXXX
保护域
类,尤其是其方法。implies(Permission)
政策
的关键方法。implies(ProtectionDomain, Permission)
代码源
,权限集合
,权限
和主体的方法
。implies
可以重写上述任何方法,以便以递增的粒度自定义概念PDP的功能。应该指出的是,JAAS确实(与其名称所暗示的相反)并没有真正带来自己的PDP;相反,它为域和策略提供了支持基于主体的查询的方法,以及代码来源的原始信任因素。因此,在我看来,您保持“JAAS兼容”的要求基本上意味着想要使用(原始加JAAS)Java SE授权模型,即沙箱,我怀疑这是否是您想要的。当标准模型被认为水平太低和/或性能密集型时,倾向于使用像Shiro这样的框架;换句话说,当授权逻辑不需要评估给定的一组信任因素的每个堆栈帧时,因为这些因素通常对上下文不敏感。根据我假设的有效性,出现了三种主要情况进行检查:
AccessControlContext
AccessControlContext
AccessControlContext
以您认为合适的方式管理身份验证。如果您希望继续使用 JAAS 的 SPI 进行身份验证,请忘记建立标准作为身份验证结果,而是直接将 Shiro 特定的标准绑定到线程本地存储。通过这种方式,您可以更方便地访问 SNAA,并避免使用(并遭受潜在的性能损失)来检索它们。javax.security.auth
Subject
AccessControlContext
子类 ,重写至少两个方法,使得它们SecurityManager
checkPermission
Permission
SecurityException
安全上下文接收重载可能直接忽略相应的参数。在应用程序初始化时,实例化并安装 () 您的实现。System::setSecurityManager
Subject
SecurityManager
checkPermission
checkPermission
Policy
implies(ProtectionDomain, Permission)
SecurityManager::checkPermission
CodeSource
checkPermission
Policy::setPolicy
以您认为合适的方式管理身份验证。不幸的是,在这种情况下,主题处理部分并不像创建一个那么简单。ThreadLocal
子类、实例化和安装 执行 和 的组合职责,如第二种情况中单独描述的那样。Policy
SecurityManager::checkPermission
Policy::implies
实例化并安装标准 。SecurityManager
创建一个能够存储和公开 SNAA 的子类。ProtectionDomain
作者1 一个域名复合者
是用SNAAs构建的;
实现这样的combine(ProtectionDomain[], ProtectionDomain[])
就像 ,实现应该是有效的(例如,通过消除重复项),因为每次 和 方法都会调用它。Policy::implies
getContext
checkPermission
AccessController
身份验证成功后,创建一个包装当前身份验证的新身份验证,以及自定义的实例,从而包装 SNAA。包装要在调用“内”在该点之外执行的代码,同时传递替换访问控制上下文。AccessControlContext
DomainCombiner
AccessController::doPrivilegedWithCombiner
1 除了使用自定义域和您自己的组合器实现之外,还有一种看似更简单的替代方法,即将 SNAA 转换为 Principal
s,并使用标准的 SubjectDomainCombiner
将它们绑定到当前 AccessControlContext
的域(如上所述,或仅通过 Subject::d oAs
)。此方法是否会降低策略的效率主要取决于调用堆栈的深度(访问控制上下文包含多少个不同的域)。最终,您认为可以避免作为域合并器的一部分实现的缓存优化将在创作策略时回击您,因此这本质上是您必须在此时做出的设计决策。