1

除了标准的用户名/密码表单身份验证之外,我们还需要实现一个支持使用另一个外部 IDP 进行身份验证/授权的 IDP。Picketlink 是否支持这种场景开箱即用?

以下是所需的组件:

  1. 多个依赖于我们的 IDP(我们称之为 IDP-Internal)进行身份验证的 SP。
  2. IDP-Internal 应该支持使用 LdapLoginModule 和 DatabaseLogingModule 对不同用户组进行用户名/密码形式的身份验证。它还应该支持使用另一个 IDP 进行身份验证(我们称之为 IDP-External)
  3. IDP-External 来自具有一些 SAML 扩展的外部提供商。

我们目前已经使用 picketlink 实现了 SP 和 IDP-Internal(遵循 picketlink 示例)。但是,IDP-Internal 到 IDP-External 的集成目前是使用一些手工/解析 SAML 请求/响应的 hacky 借用代码实现的(这里没有纠察链接)。我已经设法通过扩展 Picketlink 的 IDPWebBrowserSSOValve 将这个 hacky 代码集成到 IDP-Internal 中。此自定义 Valve 解析来自 IDP-External 的传入 SAMLResponse,并使用类似于在 SP 端完成的 SAML2LoginModule 进行本地容器身份验证。

这是自定义阀门:

public class IDPInternalAuthentiationValve extends IDPWebBrowserSSOValve {
    @Override
    public void invoke(Request request, Response response) throws IOException, ServletException {
        String samlResponseXML = request.getParameter(GeneralConstants.SAML_RESPONSE_KEY);
        if (isNotNull(samlResponseXML)) {
            // This is a SAML Response from IDP-External
            // Parse SAML and get subjectName and roles
            // Lookup subject in an internal database and get local roles
            ServiceProviderSAMLContext.push(subjectName, combinedRoles);
            // Authenticate locally using SAML2LoginModule
            Principal principal = container.getRealm().authenticate(subjectName, ServiceProviderSAMLContext.EMPTY_PASSWORD);
            ServiceProviderSAMLContext.clear();

            Session session = request.getSessionInternal(false);
            // Save the authenticated Principal in our session
            session.setNote(Constants.FORM_PRINCIPAL_NOTE, principal);

            String samlRequestFromSession = (String)session.getNote(GeneralConstants.SAML_REQUEST_KEY);
            // This is the request from SP
            if (isNotNull(samlRequestFromSession)) {
                // Send a response back to SP using the principal created above
                processSAMLRequestMessage(request, response);
            }
        } else {
            // Username/password form authentication flow
            super.invoke(request, response);
        }
    }
}

这个解决方案虽然有效,但感觉有点笨拙。有没有更好的方法来做到这一点只使用纠察队?

4

0 回答 0