更新时间:2023-11-30 15:57:22
TL;DR: Have a look at this and that for a sample solution.
您的要求取决于您使用的供应商特定功能提供的灵活性程度;您的产品可能允许也可能不允许您扩展该/这些 LoginModule
/Realm
/IdentityStore
/whatever-it's/they's 的行为-称为专有类,或者甚至可能只是在某些管理 UI 的输入字段中键入 SQL 查询.底线是它是非标准功能.
What you ask for depends on the degree of flexibility offered by the vendor-specific feature you use; your product may or may not allow you to extend the behaviour of that/these LoginModule
/ Realm
/ IdentityStore
/ whatever-it's/they're-called proprietary class(es), or maybe even to just type an SQL query into some administrative UI's input field. The bottom line is that it's non-standard functionality.
在标准的 Java EE 方面,有 JASPIC(用户/消息身份验证)和 JACC(授权)SPI.两者都可用于从某些外部存储中检索与您的用户有关的安全相关信息.JASPIC 不能做的是在认证之后改变用户的角色;也就是说,在经过身份验证的请求 1期间,用户的角色是固定的.JASPIC 也不能将含义附加到这些角色上;因为它们只是简单的 String
,AS 将以某种专有方式从中派生组 Principal
.另一方面,JACC 可以做这些事情,因为它建立了一个规则库"(想想 Policy
) 精确关联角色、主体和 Permission
s 并且可以在每次用户-系统交互时查询.JACC 还可以覆盖或更改通过部署描述符和注释表达的 Java EE 安全约束的解释.
On the standard Java EE side of the spectrum there are the JASPIC (user / message authentication) and JACC (authorization) SPIs. Both can be used to retrieve security-related information pertaining to your users from some external store. What JASPIC cannot do is change a user's roles after authentication; that is, for the duration of an authenticated request 1 the user's roles are fixed. JASPIC can also not attach meaning to those roles; for it they're just plain String
s that the AS will in some proprietary manner derive group Principal
s from. JACC, on the other hand can do those things, as it establishes a "rulebase" (think Policy
) which precisely associates roles, principals and Permission
s and can be queried on each and every user-system interaction. JACC can also override or alter the interpretation of the Java EE security constraints expressed via deployment descriptors and annotations.
我将在这篇文章中包含一个基于 JASPIC 的解决方案,并在很大程度上忽略 JACC,因为:
I will include a JASPIC-based solution in this post and disregard JACC for the most part, because:
关于以下内容的一些评论:
Some remarks on what follows:
LoginModule
(LM),通过使用 JASPIC LoginModule Bridge Profile.后一个 SAM 需要在 AS 和源级别本身进行进一步的配置/调整,除非您使用的是 GlassFish.提供了一个随附的示例 JAAS login.conf
条目.AuthConfigProvider
和 ServerAuthConfig
实现,但随后必须将实际 SAM 注册到您产品的 AuthConfigFactory
以专有方式(通过供应商特定的 foo-web.xml
和/或进一步使用部署/管理工具).您也不会让 SAM 实现 ServerAuthContext
接口,并且必须从 SAM 中加载随附的 Properties
.然后,您的 AS 将为您实例化缺少的类,可能会重用它为所有应用程序和消息层预先配置的全局"AuthConfigProvider
和/或 ServerAuthConfig
.请注意,根据它是否跨请求重用其实例化的 ServerAuthConfig
和 ServerAuthContext
(几乎没有这种情况,尤其是后者),您的 SAM 的生命周期可能会受到影响.provided
) javaee-api
7.0(加上您的 JDBC 驱动程序,除非 AS 类路径中已经存在).LoginModule
(LM), by employing the JASPIC LoginModule Bridge Profile. The latter SAM requires further configuration / adaptation, both at the AS and at the source level per se, except if you are using GlassFish. An accompanying example JAAS login.conf
entry is provided.AuthConfigProvider
and ServerAuthConfig
implementations, but will then have to register the actual SAM with your product's AuthConfigFactory
in a proprietary way (via a vendor-specific foo-web.xml
and/or further use of deployment / administrative tools). You will additionally not have the SAM implementing the ServerAuthContext
interface and will have to load the accompanying Properties
from within the SAM. Your AS will then instantiate the missing classes for you, possibly reusing a "global" AuthConfigProvider
and/or ServerAuthConfig
it has pre-configured for all applications and message layers. Note that, depending on whether it reuses its instantiated ServerAuthConfig
and ServerAuthContext
across requests (hardly ever the case especially with the latter), the lifecycle of your SAM may be affected.provided
) javaee-api
7.0 (plus your JDBC driver, unless already present on the AS class path).ServletContextListener
注册AuthConfigProvider
.另存为 /<project>/src/main/java/org/my/foosoft/authn/BigJaspicFactoryRegistrar.java
.AuthConfigProvider
.另存为 /<project>/src/main/java/org/my/foosoft/authn/BigJaspicFactory.java
.ServerAuthConfig
.另存为 /<project>/src/main/java/org/my/foosoft/authn/LittleJaspicServerFactory.java
.ServerAuthContext
- ServerAuthModule
实现助手类.这是实际答案的 1/3 部分.另存为 /<project>/src/main/java/org/my/foosoft/authn/HttpServletSam.java
./<project>/src/main/java/org/my/foosoft/authn/StandaloneLdapSam.java
./<project>/src/main/java/org/my/foosoft/authn/JaasDelegatingLdapSam.java
./<project>/src/main/java/org/my/foosoft/authn/JaspicMischief.java
.属性
.如果您想逐字测试实际的身份验证代码,请根据您的需要调整它们.另存为 /<project>/src/main/resources/org/my/foosoft/authn/jaspic-provider.properties
.login.conf
(6) 的片段;有关实际文件系统位置的信息,请参阅供应商文档./<project>/src/main/java/org/my/foosoft/presentation/UserUtils.java
(可选 - 用于演示目的:JSF 支持 bean)/<project>/src/main/webapp/index.xhtml
(可选 - 用于演示目的:不受保护的索引页面)/<project>/src/main/webapp/login.xhtml
(可选 - 用于演示目的:登录页面)/<project>/src/main/webapp/restricted/info.xhtml
(可选 - 用于演示目的:受保护的索引页面,用于角色 access_restricted_pages
)/<project>/src/main/webapp/WEB-INF/web.xml
(可选 - 出于演示目的和完整性考虑:网络模块 DD)ServletContextListener
registering the AuthConfigProvider
. Save as /<project>/src/main/java/org/my/foosoft/authn/BigJaspicFactoryRegistrar.java
.AuthConfigProvider
. Save as /<project>/src/main/java/org/my/foosoft/authn/BigJaspicFactory.java
.ServerAuthConfig
. Save as /<project>/src/main/java/org/my/foosoft/authn/LittleJaspicServerFactory.java
.ServerAuthContext
- ServerAuthModule
implementation helper class. This is part 1/3 of the actual answer. Save as /<project>/src/main/java/org/my/foosoft/authn/HttpServletSam.java
./<project>/src/main/java/org/my/foosoft/authn/StandaloneLdapSam.java
./<project>/src/main/java/org/my/foosoft/authn/JaasDelegatingLdapSam.java
./<project>/src/main/java/org/my/foosoft/authn/JaspicMischief.java
.Properties
. Adapt them to your needs if you'd like to test the actual authentication code verbatim. Save as /<project>/src/main/resources/org/my/foosoft/authn/jaspic-provider.properties
.login.conf
snippet for (6); consult vendor's documentation for actual file system location./<project>/src/main/java/org/my/foosoft/presentation/UserUtils.java
(optional - for demonstration purposes: JSF backing bean)/<project>/src/main/webapp/index.xhtml
(optional - for demonstration purposes: unprotected index page)/<project>/src/main/webapp/login.xhtml
(optional - for demonstration purposes: login page)/<project>/src/main/webapp/restricted/info.xhtml
(optional - for demonstration purposes: protected index page for users in role access_restricted_pages
)/<project>/src/main/webapp/WEB-INF/web.xml
(optional - for demonstration purposes and for the sake of completness: web module DD)进一步阅读:
Further reading:
1 JASPIC 是一个非常通用的 SPI,理论上,当插入一个有能力的消息处理运行时时,它能够验证 JMS、SAML-over-SOAP 和任何其他类型的消息.即使是它主要使用的 Servlet Container Profile 也没有过度限制它.
1 JASPIC is very a generic SPI, in theory able to authenticate JMS, SAML-over-SOAP and any other kind of message, when plugged into a capable message processing runtime. Even its predominantly used Servlet Container Profile does not overly constrain it.
JASPIC 的低级、灵活特性需要不了解特定于协议的功能,例如 HTTP 会话.因此,ServerAuthContext
s/SAM 由运行时触发以对每个请求执行身份验证.
JASPIC's low-level, flexible nature entails unawareness of protocol-specific functionality, such as the HTTP session. Consequently, ServerAuthContext
s / SAMs are triggered by the runtime to perform authentication on every request.
然而,该规范通过允许 SAM 请求运行时通过 MessageInfo
Callback 属性来发起 容器身份验证会话,为这个潜在的缺点做出了规定.当被要求对同一客户端的后续请求进行身份验证时,SAM 可以避免重复整个过程,方法是要求运行时重用先前建立的 AS 身份验证会话,因此用户身份(调用者和/或组 Principal
(s)).这是通过执行示例代码的 HttpServletSam
中显示的do-nothing-/leave-authentication-state-as-is-protocol"来实现的.
The spec however makes a provision about this potential shortcoming by allowing SAMs to request initiation of a container authentication session by the runtime, via a MessageInfo
Callback Property. When asked to authenticate subsequent requests of the same client, SAMs can avoid repeating the entire process, by asking the runtime to reuse the previously established AS authentication session, hence the user identity (caller and/or group Principal
(s)). That is accomplished via execution of the "do-nothing-/leave-authentication-state-as-is-protocol" shown in the HttpServletSam
of the sample code.
最后应该注意的是,JASPIC 和 Servlet 规范都没有明确定义容器身份验证会话是什么.对于经过 SAM 身份验证的用户,出于所有实际目的,我认为 AS 身份验证会话等同于 HTTP 会话,只要 a) 身份验证与单个应用程序上下文相关并且 b) SAM,如上所述,信号在每个请求上重用 AS 身份验证会话.
It should lastly be noted that neither the JASPIC nor the Servlet spec clearly defines what a container authentication session is. For a SAM-authenticated user I would, for all practical purposes, consider the AS authentication session to be the equivalent of the HTTP session, as long as a) authentication pertains to a single application context and b) the SAM, as explained above, signals reuse of the AS authentication session on each request.