术语说明:
- 此处的身份验证机制 (AM)指的是负责在 Java EE 运行时中生成与/在/中的身份验证的调用方实体相关的身份验证语句,并因此注册/建立身份的任何组件。此类组件可能特定于 Application Server (AS) 或 Java EE 标准;Java EE 应用程序开发人员用于扩展的 AS 实现细节或类型;作为 Java EE 应用程序的一部分或作为 AS 的一部分部署。您的JAAS
LoginModule
(LM)就是这样一个组件。虽然现在Identity Store (IS)似乎是(半)规范性术语,用于指代(除其他外)LM,但我想将其保留用于特定于应用程序的持久层(例如JPA @Entity
) 类型代表您的用户,因此必须建立这种(定义不明确的)区别。“你为什么含糊不清?”,你可能会问,“你不能把 LM 称为 LM 吗?”。因为我对 JBoss LM 一无所知!事实上,我既不是 JBoss 用户,也不是在 Java EE 中使用 JAAS 的人。尽管如此,我觉得我可以提供一个适用于一般情况的答案,因此不可避免的含糊不清。
- 停用用户指的是您的“即将被踢出的用户”,即,其权限(组、角色、权限——无论在那里调用什么)已被撤销的用户。 IS级别的某种方式。
首先,没有标准的 Java EE API 可以将任意用户的
Subject
or暴露给您的代码。
HttpSession
理论上,您可以自己记录该信息,例如在身份验证期间,但我会假设这不是您想要的。此外,
Subject
具体而言,虽然没有标准明确禁止在代表
Principal
的请求服务期间对其(/凭据集合)进行修改,但
也Subject
没有声明必须这样做。实际上,甚至不清楚
当前经过身份验证的调用者(在身份验证期间填充并可以通过
JACC检索的调用者)是否
必须Subject
"javax.security.auth.Subject.container"
PolicyContextHandler
与运行
Policy
时在做出授权决策时查询的数据结构一致;也就是说,运行时可能只为您提供一个副本,在内部使用经过身份验证的调用者的完全不同的表示,或者介于两者之间。因此,即使您能够修改
Subject
,这样做也不一定会影响有效的安全上下文。
继续可以做的事情。您的需求可以在身份验证和/或授权方面得到解决,前一种方法比后一种方法更容易使用。由于您没有回答我的评论,因此我将简要介绍其两个可能的答案。
禁止呼叫者重新认证
一旦应用程序停用了用户,它必须以某种方式指示 AM 在他们发出的后续请求中停止重新验证他们。为了减少耦合,应用程序通常不会直接与 AM 通信,而是满足后者评估的某些条件。例如,应用程序可能会为用户分配一些特殊的“locked_out”权限,或者设置一个HttpSession
属性。当被要求重新验证停用的用户时,AM 将确认停用并拒绝重新验证他们。随后它将使用户的会话无效。它将如何完成这取决于它的种类和实施。为此,您的 LM 可能不得不利用"javax.servlet.http.HttpServletRequest"
JACC PolicyContextHandler
。贾斯皮克_ ServerAuthModule
将立即访问请求实例,并将其作为validateRequest
参数接收。其他一些组件可能不得不求助于使用 AS 内部,或者让应用程序承担会话失效的责任(一些调用拦截组件,例如Servlet Filter
,必须第二次查询 IS 并采取相应措施)。
上述方法显然需要能够修改 AM 的功能。此外,缓存 AM 需要在重新使用其先前建立的身份验证结果之前评估所述停用条件。最后,如评论中所述,如果在用户的 IS 访问撤销时,代表该用户的请求正在接受服务(在访问撤销事件发生之前已到达/已通过身份验证) ,该请求的服务将正常完成(除非应用程序请求重新验证该用户,例如通过HttpServletRequest#
(login
| authenticate
)。
禁止来电重新授权
虽然,正如我在开始时提到的,用户的Subject
s 不容易检索/修改,但Policy
在符合 JACC 的 Java EE 运行时上,那些获得授权的支持实际上是。不幸的是,默认的 AS 提供的 JACC 提供程序 ( PolicyConfiguration
+ Policy
) 有一个严重的限制:它只允许您对 Java EE角色进行操作,而不是对映射到Principal
的调用者进行操作,即“拥有”这些角色。例如,默认提供程序允许您扩展映射到“admin”角色的 s ;它允许您删除“管理员”角色及其所有角色;但它不允许你决定谁Permission
Principal
Permission
成为“管理员”——至少不是以标准方式。
就 JACC 而言,这个限制基本上给您留下了两种选择:或者让 AM为每个调用者添加一个“虚拟”组 ,与相应调用者的名称相同。然后,在用户停用时,添加(通过)与“虚拟”组有关的自定义。最后,从“应用程序空间”代码中检查(例如,通过 AccessController#checkPermission)用户是否有,如果有,将他们踢出。但是等等,这完全没有意义——如果它不能自己处理授权,为什么还要费心使用呢?另一种方法是编写和安装您自己的 JACC 提供程序。这样做可以让您完全控制Principal
Subject
Principal
PolicyConfiguration#addToRole
Permission
Permission
Policy
Principal
-/group-to-role 映射,使您能够随心所欲地采取行动,授权明智的,从那时起使用该信息。不过,编写一个新的提供者并非易事,特别是因为它必须适应JRE范围内的授权需求,而不仅仅是在单个应用程序的范围内。我怀疑您的要求是否证明了如此高的工作量是合理的。如果您仍然想走这条路,那么 Arjan Tijms博客上与 JACC 相关的文章是一个很好的起点。