响应的InResponseToField与发送的消息不对应:SAML错误SpringSecurity-4.2.13-RELEASE

问题描述

我的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,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());
    }
}

解决方法

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

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...