如何从 Java 与 ADFS 通信?

How do I talk to ADFS from Java?

我们有一个关于 Caucho Resin 的网站 运行。它主要使用 JSP 在 Java 中编写。我们在网站上有自己的自定义身份验证。 (我们没有使用任何第三方身份验证框架。)我们现在希望支持使用 SAML 的联合。 IdP 主要是 运行 ADFS,但我的问题是关于 SAML。特别是,我如何使用 OpenSAML、Shibboleth 或其他一些 Java 兼容选项与我们 Java 应用程序 的上游 IdP 联合?

编辑:另一个选项是 OAuth。优点?缺点?

您的应用程序需要充当 SAML SP,直接(通过您的代码)或间接(例如,通过对反向代理、应用程序服务器等的 SAML SP 支持)。

对于直接选项(这需要对您的应用程序进行更多修改),您可以:

  • 自己编写 SAML SP(最有可能使用 OpenSAML,您可以在现有产品的来源中找到示例)
  • 使用现成的产品集成到您的应用程序中,例如Spring SAML or OpenAM Fedlet

对于间接选项(需要对您的应用程序进行较少的修改),您可以:

  • 在您的 Apache 反向代理上使用 Shibboleth SAML SP plugins or mod_auth_mellon(如果您使用一个)
  • 将 SAML SP 部署为容器上的另一个应用程序(例如 Spring SAML 或 OpenAM)并使其与您的应用程序通信 - 因此 SAML SP 执行与 ADFS 的身份验证并将其与您的应用程序通信,例如通过共享 cookie 或自定义令牌

您可以找到更多比较细节和注意事项in this thread

ADFS 3 应该支持 OAuth 授权服务器,它可能是一种更简单的集成方式,请参阅 here and here。使用 OAuth 实施身份验证通常比 SAML 容易得多,没有相关缺点。

Caucho 提供的树脂验证器不会帮助联邦。相反,您需要添加一个 ServletFilter 来查找未经身份验证的用户。当它找到一个时,您应该将他们引导至登录页面。在这一点上,您应该询问用户是否想直接登录到您的站点或联合到另一个组织。 (这可以通过显示 username/password 表单 + 受信任第三方的徽标来完成。)在前者中,直接登录的情况下,使用 Resin Authenticator 来检查您的本地用户存储库,或者您现在正在做的.对于联合案例,使用 SAML。

联合将从向受信任的合作伙伴(ADFS 服务器)发送身份验证请求开始。这是 a little XML document 打包成一个表单,需要根据请求更改一些内容(例如,创建时间)。这可以用 String.format 来完成——没什么复杂的。将此身份验证请求发送到用户选择的组织中的 SAML 服务器(即 ADFS)。他们将登录并将身份验证响应发送到您需要创建的某些“断言消费者服务”。

ACS 只是一个接收 SAML 身份验证响应的端点。这需要是一个未经身份验证的端点,它将解析和验证来自 ADFS 的回复。使用 OpenSAML 来执行此操作。您需要做很多事情来确保它是有效的。例如,您必须验证断言的数字签名。您还需要检查发布时间,它不是在未来。通过检查确认数据中的 Destination、受众和收件人来验证断言是否适合您。等等等等

如果这超出了您想要编码的范围,请检查开源或商业 SAML 服务器。它需要作为一个 SP 发挥作用,并且应该 运行 在 Resin 中以保持简单。 Asimba 是一位中庸而精干的候选人。您可以将它部署到 Resin 中,它会处理请求和回复。

关于 OAuth 的注意事项

您在这里考虑的是联合(或 Web 单点登录)。 OAuth 不适合联合。它是一种旨在进行委托授权的协议。 OpenID Foundation 已扩展 OAuth 2 以支持 OAuth 的 OpenID Connect 配置文件中的联合。 ADFS 不支持此联合协议,并且仅限于 WS-Federation 和 SAML。因此,如果您的合作伙伴将使用 ADFS,则您不应该研究 OAuth。