0

我的 Web 应用程序部署在 Amazon ECS 上并使用 ALB 并从堡垒主机访问此应用程序。我正在使用 Okta 进行 SSO。登录页面已成功重定向到 Okta,并且在请求返回到应用程序服务器时经过身份验证后,我收到以下错误 -

Caused by: org.opensaml.common.SAMLException: InResponseToField of the Response doesn't correspond to sent message a491gda80cgh3a2b5bb3j8ebd515d2
    at org.springframework.security.saml.websso.WebSSOProfileConsumerImpl.processAuthenticationResponse(WebSSOProfileConsumerImpl.java:139)

我正在使用 CustomSAMLContextProvider 并将 MessageStorageFactory 设置为 EmptyStorageFactory,如其他答案中所建议的那样。我不确定为什么此检查仍在进行。

这是我的自定义 SAMLContextProviderImpl 类 -

public class SAMLMultipleEndpointContextProvider extends SAMLContextProviderImpl {

    /**
     * Creates a SAMLContext with local entity values filled. LocalEntityId is set to server name of the request. Also
     * request and response must be stored in the context as message transports.
     *
     * @param request  request
     * @param response response
     * @return context
     * @throws MetadataProviderException in case of metadata problems
     */
    @Override
    public SAMLMessageContext getLocalEntity(HttpServletRequest request, HttpServletResponse response) throws MetadataProviderException {

        SAMLMessageContext context = new SAMLMessageContext();
        populateGenericContext(request, response, context);
        populateLocalEntityId(context, request.getServerName());
        populateLocalContext(context);
        return context;
    }

    /**
     * Creates a SAMLContext with local entity and peer values filled. LocalEntityId is set to server name of the
     * request. Also request and response must be stored in the context as message transports. Should be used when both
     * local entity and peer entity can be determined from the request.
     *
     * @param request  request
     * @param response response
     * @return context
     * @throws MetadataProviderException in case of metadata problems
     */
    @Override
    public SAMLMessageContext getLocalAndPeerEntity(HttpServletRequest request, HttpServletResponse response) throws MetadataProviderException {

        SAMLMessageContext context = new SAMLMessageContext();
        populateGenericContext(request, response, context);
        populateLocalEntityId(context, request.getServerName());
        populateLocalContext(context);
        populatePeerEntityId(context);
        populatePeerContext(context);
        return context;
    }

    /**
     * Populate LocalEntityId with retrieved entityId from metadata manager using given localAlias parameter value.
     */
    @Override
    public void populateLocalEntityId(SAMLMessageContext context, String localAlias) throws MetadataProviderException {
        String entityId = metadata.getEntityIdForAlias(localAlias);
        QName localEntityRole = SPSSODescriptor.DEFAULT_ELEMENT_NAME;

        if (entityId == null) {
            throw new MetadataProviderException("No local entity found for alias " + localAlias + ", verify your configuration.");
        } else {
            logger.debug("Using SP {} specified in request with alias {}", entityId, localAlias);
        }

        context.setLocalEntityId(entityId);
        context.setLocalEntityRole(localEntityRole);
    }

    /**
     * Disable the check for InResponseToField from SSO message response.
     */
    @Override
    public void setStorageFactory(SAMLMessageStorageFactory storageFactory) {
        super.setStorageFactory(new EmptyStorageFactory());
    }
}
4

1 回答 1

0

为了遵守 SAML 规范中定义的规则,必须根据 SP 发起的 SSO 流中的 SAML AuthNRequest 验证 SAML 响应。默认情况下,Spring SAML 将 SAML AuthNRequest 存储在内存中,因此包含 SAML 响应作为有效负载的 HTTP POST 请求必须命中创建 AuthNRequest 的同一 JVM。如果 LB 不能保证粘性,那么就需要实现一个可以与多个实例共享消息的消息存储(org.springframework.security.saml.storage.SAMLMessageStorage, org.springframework.security.saml.storage.SAMLMessageStorageFactory)。确保在消费后从存储中删除消息以规避重放攻击,因为 SAML 响应是一次性使用的。

于 2020-10-12T12:18:24.943 回答