挂起容器请求LDAP用户角色的进程

在我的应用程序中,我使用基于表单的身份validation和LDAP-Realm。 对于授权,我使用数据库。 据我所知,这工作如下

App --> (user, pass) --> LDAP  ask for security roles for 'user' --> JACC / Database <-- Administrator -- 

我可以挂钩我的应用程序调用的进程ask for security roles for 'user'吗?

背景:

LDAP说: Okay, 'user' is authentified

数据库: give me all roles where username = user

现在我想自定义数据库查询: give me all roles where username = 'user' AND some more attributes

这有点可能吗?

TL; DR:看看这个和那个样本解决方案。


您要求的内容取决于您使用的供应商特定function提供的灵活程度; 您的产品可能会也可能不会允许您扩展该/ LoginModule / Realm / IdentityStore /其他任何/他们所谓的专有类的行为,甚至可能只是在某些管理UI中键入SQL查询输入字段。 底线是它的非标准function。

在频谱的标准Java EE方面,有JASPIC (用户/消息认证)和JACC (授权)SPI。 两者都可用于从某些外部存储中检索与用户相关的安全相关信息。 JASPIC不能做的是认证改变用户的角色; 也就是说,在经过身份validation的请求 1的持续时间内,用户的角色是固定的 。 JASPIC也不能这些角色赋予意义 ; 对于它来说,它们只是简单的String ,AS将以某种专有的方式从中获取组Principal 。 另一方面,JACC可以做这些事情,因为它建立了一个“规则库”(思考Policy ),它可以精确地关联角色,主体和Permission并且可以在每个用户系统交互中查询。 JACC还可以覆盖或更改通过部署描述符和注释表达的Java EE安全性约束的解释。

我将在这篇文章中包含一个基于JASPIC的解决方案,并且大部分时间忽略JACC,因为:

  • 您可能不需要JACC提供的额外灵活性。
  • 使用自定义JACC提供程序解决方案需要相当 多 的工作,并且由于AS特定的组到角色映射而仍然不是100%标准。
  • 我不知道一个开源项目使用自定义JACC提供程序来完成有意义的事情; Java EE完整配置文件 – 实现AS是唯一的例外,因为它们被强制实施规范,有时也在内部使用它们的JACC提供程序(例如,在GlassFish的情况下)。
  • 围绕JASPIC仍然存在很多混乱(很多开发人员都不知道它甚至存在),这是两个规范中最简单的一个。 在继续介绍JACC之前,首先让JASPIC为更多人所知和“平易近人”是不合理的。
  • 虽然现在JASPIC在线上只有很少的很好的例子,以及通过JASPIC提供商实施实际身份validation的项目,如果我错了,请纠正我 – 我还没有在SO上找到完整的JASPIC示例。

关于以下内容的一些评论:

  • 如果您的应用程序/ AS /系统爆炸或被外星人等攻击,则不保证/使用风险/不起诉我
  • 请尽量忽视那些优化,更好的设计或其他改进在您认为必不可少的地方。 是的,你可以承认重用DB / LDAP连接; validation插入LDAP搜索filter的用户名; 更关心线程安全; 使用TLS; 为非格式良好的XML有效负载返回400 … 解决这些问题超出了所提供解决方案的范围。 劳驾?? 你想知道unit testing在哪里???! 对不起,从来没有听说过这个词! 🙂
  • 提供了具体执行组(角色)的身份validation和检索的两个SAM:“独立”,它自己完成两个任务,以及“委托”任务,顾名思义,它演示了SAM如何委派实际身份validation通过使用JASPIC LoginModule Bridge Profile工作到JAAS LoginModule (LM)。 后者SAM需要在AS和源级本身进行进一步的配置/调整,除非您使用的是GlassFish。 提供了附带的示例JAAS login.conf条目。
  • 提供程序类已针对GlassFish 4.1进行了测试。 他们努力保持规范兼容,因此,如果您的产品实现了完整的Java EE(6,最好是7)配置文件,那么它应该真正适用于您的AS(显然除了第二个SAM)。 如果没有,我很抱歉; 不,我不会测试你的AS。
  • 您可以避免学习/使用AuthConfigProviderServerAuthConfig实现,但必须以专有方式(通过特定于供应商的foo-web.xml和/或进一步使用部署/管理工具)向您的产品的AuthConfigFactory注册实际SAM )。 您还将没有SAM实现ServerAuthContext接口,并且必须从SAM中加载附带的Properties 。 然后,您的AS将为您实例化缺少的类,可能重用已为所有应用程序和消息层预先配置的“全局” AuthConfigProvider和/或ServerAuthConfig 。 请注意,根据它是否在请求之间重用其实例化的ServerAuthConfigServerAuthContext (特别是后者几乎没有这种情况),SAM的生命周期可能会受到影响。
  • 不包括组到角色映射,因为它是特定于容器的。
  • 无论我在哪里这样做,我都会收到评论。 并非所有(完全)都无用。 在规范的帮助下,代码应该是可理解的 – 但是可以随意询问是否有什么问题困扰着你。 为超长的post道歉。
  • 路径绝对来自标准Maven项目的根。 一旦在SAM中调整了属性和/或身份validation/组检索方法,就可以将所有文件构建为WAR,并在AS上按原样部署后者进行测试。 唯一的依赖是( providedjavaee-api 7.0(加上你的JDBC驱动程序,除非已存在于AS类路径中)。
  • 由于SO的post长度限制,我不得不将代码移动到Gist 。

  1. ServletContextListener注册了AuthConfigProvider 。 保存为//src/main/java/org/my/foosoft/authn/BigJaspicFactoryRegistrar.java
  2. AuthConfigProvider 。 保存为//src/main/java/org/my/foosoft/authn/BigJaspicFactory.java
  3. ServerAuthConfig 。 保存为//src/main/java/org/my/foosoft/authn/LittleJaspicServerFactory.java
  4. 基本的双ServerAuthContextServerAuthModule实现助手类。 这是实际答案的1/3。 保存为//src/main/java/org/my/foosoft/authn/HttpServletSam.java
  5. 独立的SAM实施。 实际答案,第2/3部分。 保存为//src/main/java/org/my/foosoft/authn/StandaloneLdapSam.java
  6. JAAS LM委托SAM 。 实际答案,第3/3部分。 保存为//src/main/java/org/my/foosoft/authn/JaasDelegatingLdapSam.java
  7. 便利例外类型 。 保存为//src/main/java/org/my/foosoft/authn/JaspicMischief.java
  8. 随附的Properties 。 如果您想逐字测试实际的身份validation代码,请根据您的需要调整它们。 保存为//src/main/resources/org/my/foosoft/authn/jaspic-provider.properties
  9. 附带示例login.conf片段(6); 请参阅供应商的文档,了解实际的文件系统位置。
  10. //src/main/java/org/my/foosoft/presentation/UserUtils.java (可选 – 用于演示目的: JSF支持bean )
  11. //src/main/webapp/index.xhtml (可选 – 用于演示目的: 不受保护的索引页面 )
  12. //src/main/webapp/login.xhtml (可选 – 用于演示目的: 登录页面 )
  13. //src/main/webapp/restricted/info.xhtml (可选 – 用于演示目的:角色access_restricted_pages用户的受保护索引页 )
  14. //src/main/webapp/WEB-INF/web.xml (可选 – 用于演示目的和为了完整性: web模块DD )

进一步阅读:

  1. JSR-196(JASPIC)规范
  2. Arjan Tijms的 JASPIC ZEEF页面
  3. JSR-115(JACC)规范

1 JASPIC是一个非常通用的SPI,理论上可以在插入有能力的消息处理运行时时对JMS,SAML-over-SOAP和任何其他类型的消息进行身份validation。 即使其主要使用的Servlet容器配置文件也不会过度限制它。

JASPIC的低级,灵活性质意味着不了解特定于协议的function,例如HTTP会话。 因此, ServerAuthContext s / SAM由运行时触发,以对每个请求执行身份validation。

然而,该规范通过允许SAM通过MessageInfo Callback Property请求运行时启动容器认证会话来对此潜在缺点做出规定。 当要求对同一客户端的后续请求进行身份validation时,SAM可以通过要求运行时重用先前建立的AS身份validation会话来避免重复整个过程,从而重用用户身份(呼叫者和/或组Principal )。 这是通过执行示例代码的HttpServletSam中显示的“do-nothing- / leave-authentication-state-as-is-protocol”来完成的。

最后应该注意的是,JASPIC和Servlet规范都没有明确定义容器认证会话是什么。 对于SAM认证用户,出于所有实际目的,我会认为AS认证会话等同于HTTP会话,只要a)认证属于单个应用程序上下文并且b)SAM,如上所述,表示在每个请求上重用AS认证会话。

您可以使用Spring Security对其进行自定义,对LDAP进行身份validation并配置身份validation管理器/身份validation提供程序: