如何将JAAS授权检查委托给Shiro?

| 我正在开发一个需要基于对象的身份验证和授权的服务器端应用程序。我喜欢Shiro的简单性,但是为了与JAAS兼容,我编写了一个LoginModule,它使用Apache Shiro作为底层机制。 但是我的问题是我找不到将JAAS授权检查委托给Shiro的方法。我该如何实现?     
已邀请:
注意:答案解决了通过标准安全框架将外部授权系统与JVM集成在一起的一般情况。正如我所不熟悉的,它不是特定于Shiro或JMX的。 从概念上讲,您似乎在策略决策点(PDP)之后–即评估授权查询(\“是否允许实体X进行Y?\”)的工具。 JDK提供了以下几种: 有效的“ 0”,特别是其“ 1”组方法。
ProtectionDomain
类,尤其是its3ѭ方法。 有效的
Policy
的关键
implies(ProtectionDomain, Permission)
方法。 其次,
CodeSource
PermissionCollection
Permission
Principal
implies
方法。 可以忽略任何前述方法,以便以递增的粒度自定义概念性PDP的功能。应该指出的是,JAAS确实(与其名称所暗示的相反)并没有真正带来其自己的PDP。而是,它为域和策略提供了支持基于主体的查询的方法,以及代码源的原始信任因子。因此,在我看来,您对保留“与JAAS兼容”的要求基本上转化为想要使用(原始加JAAS)Java SE授权模型(又称为沙盒),我怀疑这是您所需要的。当标准模型被认为太低级和/或性能密集时,倾向于使用诸如Shiro之类的框架。换句话说,当授权逻辑不需要为给定的一组信任因子评估每个单个堆栈帧时,由于这些因素对上下文的敏感性比对上下文无关的更为频繁。根据我的假设的有效性,出现了三种主要的检查案例: 授权是独立于“ 11”的。 Shiro本地授权属性(SNAA),无论它们是什么,都适用于整个线程。代码来源无关紧要。 代码源很重要,要求使用沙箱。 SNAA仍然独立于“ 11”。 代码来源和SNAA都是相关的并且与ѭ11相关。 1.仅基于SNAA的授权 管理身份验证,但是您认为合适。如果您希望继续使用JAAS的“ 14” SPI进行身份验证,则不必建立标准的“ 15”作为身份验证结果,而是直接将Shiro特定的线程绑定到线程本地存储。这样,您可以更方便地访问SNAA,而不必为检索而使用
AccessControlContext
(并可能遭受性能损失)。 子类
SecurityManager
,至少重写两个
checkPermission
方法,以便它们 在必要时将“ 9”论点翻译成Shiro的PDP(SPDP)理解的内容 委托具有线程本地SNAA和许可的SPDP(如果SPDP发出信号拒绝访问,则抛出“ 20”)。 接收安全上下文的重载可以简单地忽略相应的参数。在应用程序初始化时,实例化并安装(
System::setSecurityManager
)您的实现。 2.混合授权,将代码源与上下文无关的SNAA结合在一起 管理身份验证,但是您认为合适;再次将Shiro特定的ѭ15与线程本身相关联。 子类
SecurityManager
,至少重写两个
checkPermission
方法,这一次使它们委派给SPDP和/或重写的实现(依次调用
checkPermission
相应地调用当前或提供的访问控制上下文)。对于任何给定的权限,应咨询哪个和哪些顺序,这当然取决于实现。当两者都被调用时,应该首先查询SPDP,因为它的响应速度可能比访问控制上下文快。 如果SPDP要另外处理对源自某个位置和/或一组代码签名者的代码所授予的权限的评估,则还必须子类化“ 5”,实现“ 4”,以便像上面的“ 28”一样,它传递对代码的一些可理解的表示。 SPDP的域(通常仅是其“ 7”)和权限参数(但逻辑上不是SNAA)。该实现应尽可能高效,因为它将在“ 18”时在每个域的每个访问控制上下文中调用一次。实例化并安装(
Policy::setPolicy
)您的实现。 3.混合授权,将代码源与SNAA结合在一起,两者均与上下文相关 管理身份验证,但是您认为合适。不幸的是,在这种情况下,主题处理部分并不像创建
ThreadLocal
那样简单。 子类化,实例化并安装一个ѭ5,它执行
SecurityManager::checkPermission
Policy::implies
的组合职责,如第二种情况中单独描述的。 实例化并安装标准的“ 0”。 创建一个
ProtectionDomain
子类,该子类能够存储和公开SNAA。 作者1
DomainCombiner
由SNAA构建; 实施
combine(ProtectionDomain[], ProtectionDomain[])
它使用自定义实现的等效实例替换第一个(“当前”上下文)数组参数的域; 然后将第二个参数(“ assigned”或“ heriteded”上下文)附加到原样;最后 返回串联。 像
Policy::implies
一样,实现应该是高效的(例如,通过消除重复项),因为每次
getContext
checkPermission
43ѭ方法都会被调用。 成功通过身份验证后,创建一个新的
AccessControlContext
,将当前的wrap11和一个自定义
DomainCombiner
的实例包装在一起,依次包装SNAA。包装要执行的代码 该点“在”内部“ѭ46”调用,同时传递替换访问控制上下文。 1除了使用自定义域和您自己的合并器实现外,还有一种似乎更简单的替代方法是将SNAA转换为
Principal
,并使用标准
SubjectDomainCombiner
将它们绑定到当前
AccessControlContext
的域(如上所述,或仅通过
Subject::doAs
)。此方法是否降低策略的效率主要取决于调用堆栈的深度(访问控制上下文包含多少个不同的域)。最终,您认为本可以避免作为域合并器一部分实现的缓存优化将在编写策略时反击您,因此,这实际上是您此时必须做出的设计决策。     

要回复问题请先登录注册