Apache Tomcat 1.7 如何将附加参数传递给 JAAS
Posted
技术标签:
【中文标题】Apache Tomcat 1.7 如何将附加参数传递给 JAAS【英文标题】:Apache Tomcat 1.7 How to pass additional parameters to JAAS 【发布时间】:2015-11-01 11:26:30 【问题描述】:根据 Apache Tomcat 1.7 文档:
编写您自己的基于 JAAS 的 LoginModule、User 和 Role 类(请参阅 JAAS 身份验证教程和 JAAS 登录模块开发人员指南),由 JAAS 登录上下文 (javax.security.auth.login.LoginContext) 管理你的LoginModule,注意JAASRealm内置的CallbackHandler目前只识别NameCallback和PasswordCallback。
它只支持 NameCallback 和 PasswordCallback。我想将其他参数传递给 JAAS 登录模块,但由于此限制而无法传递。
如何将其他参数传递给 JAAS 登录模块?
【问题讨论】:
您在 jaas.config 文件中定义它们以及登录模块并在初始化期间检索它们。 @EJP 我正在使用我在 context.xml 中定义的默认 tomcat org.apache.catalina.realm.JAASRealm。这个 JAASRealm 默认调用它自己的回调处理程序。即使我定义了自定义回调处理程序,JAASRealm 也不会调用它。如何强制在我的 context.xml 中定义的这个 JAASRealm 使用这个自定义回调处理程序? Tomcat 1.7,确定吗?或者更确切地说是Tomcat 7,如您使用的标签所示? 您似乎在这里感到困惑。 JAAS 领域调用登录模块,并且它们 调用处理程序。您将不得不编写自己的登录模块来调用您的处理程序。 @EJP 我想你误解了我的意思。 Tomcat JAASRealm (org.apache.catalina.realm.JAASRealm) 不需要创建 LoginContext。仅供参考,LoginContext 允许使用自定义回调处理程序。由于 Tomcat JAASRealm 不需要,这意味着它使用自己的回调处理程序。这就是我现在遇到的问题 【参考方案1】:编写自己的 CallbackHandler。详情见http://docs.oracle.com/javase/7/docs/technotes/guides/security/jaas/tutorials/GeneralAcnOnly.html
例如,MyCallbackHandler 可以支持额外的 TextOutputCallback
public void handle(Callback[] callbacks)
throws IOException, UnsupportedCallbackException
for (int i = 0; i < callbacks.length; i++)
if (callbacks[i] instanceof TextOutputCallback)
// display a message according to a specified type
. . .
else if (callbacks[i] instanceof NameCallback)
// prompt the user for a username
. . .
else if (callbacks[i] instanceof PasswordCallback)
// prompt the user for a password
. . .
else
throw new UnsupportedCallbackException
(callbacks[i], "Unrecognized Callback");
【讨论】:
我确实这样做了,但是 context.xml 中定义的默认 org.apache.catalina.realm.JAASRealm 没有调用它。它调用其他回调处理程序。如何强制此 JAASRealm 调用我的自定义回调处理程序? 查看 org.apache.catalina.realm.JAASRealm 源代码,我发现它总是使用 new JAASCallbackHandler() 来传递回调处理程序。我开始认为用 Tomcat 的 JAAS 设置自定义是不可能的。在独立应用程序中,您将使用您的处理程序创建一个 LoginContext: loginContext = new LoginContext("Sample", new MyCallbackHandler()); 那么这里的解决方案是什么? 我们回过头来问:为什么需要一个额外的参数?你有什么用? 我正在建立一个家庭顾问网站,客户可以登录并请求承包商提供服务。承包商也可以登录注册为专业承包商。实际的身份验证在 JAAS 登录模块中。将使用 LDAP 身份验证检查此用户名。但是,LDAP 身份验证需要知道此用户名是客户还是承包商。客户用户名,例如abcdef 应该以客户身份成功登录,但如果将其用作承包商用户名,则应该会失败。指示客户或承包商的 JAAS 需要附加参数【参考方案2】:解决此问题的常规方法是将您的contractor
和customer
组映射到角色。
如果您决定将来迁移到成熟的 Java EE 解决方案(例如 JBossAS/WildFly、Glassfish、WebSphere 等),使用这种基于规范的方法还有一个额外的好处,即确保您的解决方案是可移植的。
此外,如果您能够迁移到 Tomcat 8,您将可以访问 Servlet 3.1 规范中添加的其他身份验证功能。
【讨论】:
如果一个用户有多个角色会发生什么?在仅使用用户名/密码的登录屏幕上,该人登录时将是哪个角色?请记住,不同的角色可能会对不同的页面提供不同的授权访问 此解决方案允许多个角色。这取决于您如何管理。如果用户既是contractor
又是customer
,应该发生什么?
是的。假设用户 abc 既是承包商又是客户。每个角色对某些屏幕都有自己的访问权限。在登录屏幕 abc 只需使用他的 ID 和密码登录。服务器会知道哪些角色?服务器端无法知道。解决方案您需要登录屏幕,其中包含另一个字段,通知服务器用户 abc 现在以承包商身份登录(例如)。然后服务器知道将承包商角色分配给 abc 并允许他访问与承包商(而不是客户)相关的屏幕。现在看到图片了吗?
没有。关键是服务器确实知道。例如,您可以随时在 servlet 中测试:if (httpServletRequest.isUserInRole("contractor")) ...
我了解 javaee 安全模型。让我们回到基础。此用户 abc 具有在 LDAP 中定义的客户和承包商角色。在登录屏幕上,用户 abc 使用 abc/password 登录。 JAAS 应该为这个新登录的 abc 分配哪个角色?您的语句“isUserInRole”仅在分配角色并用于授权不同资源后发生。【参考方案3】:
最简单的方法:将所有参数连接成一个字符串,然后再拆分
【讨论】:
是的。我想到了这个,尽管它真的不是一个好东西。我没有看到任何其他解决方案。这么简单的问题,Tomcat竟然解决不了,太意外了以上是关于Apache Tomcat 1.7 如何将附加参数传递给 JAAS的主要内容,如果未能解决你的问题,请参考以下文章
从 Tomcat 6 JDK 1.6 迁移到 Tomcat 7 JDK 1.7 会话问题