使用spring-SAML在Pentaho中登录多租户SSO后重定向

问题描述

我想使用SAML插件Link(扩展了Spring SAML)为Pentaho配置多租户SSO登录

现在,我在blueprint.xml中声明了多个服务提供商(SP)和身份提供商(IDP)(每个租户一个,再加上一个公共SP)。但是,在登录流程结束时,我没有重定向到主页,而是重定向到一般错误页面


以下是SAML插件中blueprint.xml设置的示例:

  <bean id="spResourceFactoryCommon" class="org.pentaho.platform.spring.security.saml.resources.MetadataResourceFactory">
    <argument>
      <map key-type="java.lang.String" value-type="java.lang.String">
        <entry key="org.opensaml.util.resource.FileSystemResource" value="${saml.sp.Metadata.filesystem.common}" />
      </map>
    </argument>
    <argument value="${saml.sp.Metadata.classpath.fallback}" />
  </bean>

  <bean id="spResourceFactoryTenant1" class="org.pentaho.platform.spring.security.saml.resources.MetadataResourceFactory">
    <argument>
      <map key-type="java.lang.String" value-type="java.lang.String">
        <entry key="org.opensaml.util.resource.FileSystemResource" value="${saml.sp.Metadata.filesystem.tenant1}" />
      </map>
    </argument>
    <argument value="${saml.sp.Metadata.classpath.fallback}" />
  </bean>

  <bean id="spResourceFactoryTenant2" class="org.pentaho.platform.spring.security.saml.resources.MetadataResourceFactory">
    <argument>
      <map key-type="java.lang.String" value-type="java.lang.String">
        <entry key="org.opensaml.util.resource.FileSystemResource" value="${saml.sp.Metadata.filesystem.tenant2}" />
      </map>
    </argument>
    <argument value="${saml.sp.Metadata.classpath.fallback}" />
  </bean>

  <bean id="idpResourceFactoryTenant1" class="org.pentaho.platform.spring.security.saml.resources.MetadataResourceFactory">
    <argument>
      <map key-type="java.lang.String" value-type="java.lang.String">
        <entry key="org.opensaml.util.resource.FileSystemResource" value="${saml.idp.Metadata.filesystem.tenant1}" />
      </map>
    </argument>
    <argument value="${saml.idp.Metadata.classpath.fallback}" />
  </bean>

  <bean id="idpResourceFactoryTenant2" class="org.pentaho.platform.spring.security.saml.resources.MetadataResourceFactory">
    <argument>
      <map key-type="java.lang.String" value-type="java.lang.String">
        <entry key="org.opensaml.util.resource.FileSystemResource" value="${saml.idp.Metadata.filesystem.tenant2}" />
      </map>
    </argument>
    <argument value="${saml.idp.Metadata.classpath.fallback}" />
  </bean>

  <!-- MetadataManager configuration - paths to Metadata of IDPs and SP's  -->
  <bean id="Metadata" class="org.springframework.security.saml.Metadata.CachingMetadataManager" depends-on="pentahoSamlBootstrap">
    <argument>
      <list>
        <!-- sp Metadata with extended Metadata -->
        <bean class="org.springframework.security.saml.Metadata.ExtendedMetadataDelegate">
          <argument>
            <bean class="org.opensaml.saml2.Metadata.provider.ResourceBackedMetadataProvider">
              <argument>
                <bean class="java.util.Timer"/>
              </argument>
              <argument>
                <bean factory-ref="spResourceFactoryCommon" factory-method="factoryResource" />
              </argument>
              <property name="parserPool" ref="parserPool"/>
            </bean>
          </argument>
          <argument>
            <bean class="org.springframework.security.saml.Metadata.ExtendedMetadata">
              <property name="idpdiscoveryEnabled" value="${saml.discovery.idp.enabled}"/>
              <property name="requirelogoutRequestSigned" value="${ensure.incoming.logout.request.signed}"/>
              <property name="alias" value="pentahoCommon"/>
              <property name="local" value="true"/>
            </bean>
          </argument>
        </bean>
        <bean class="org.springframework.security.saml.Metadata.ExtendedMetadataDelegate">
          <argument>
            <bean class="org.opensaml.saml2.Metadata.provider.ResourceBackedMetadataProvider">
              <argument>
                <bean class="java.util.Timer"/>
              </argument>
              <argument>
                <bean factory-ref="spResourceFactoryTenant1" factory-method="factoryResource" />
              </argument>
              <property name="parserPool" ref="parserPool"/>
            </bean>
          </argument>
          <argument>
            <bean class="org.springframework.security.saml.Metadata.ExtendedMetadata">
              <property name="idpdiscoveryEnabled" value="${saml.discovery.idp.enabled}"/>
              <property name="requirelogoutRequestSigned" value="${ensure.incoming.logout.request.signed}"/>
              <property name="alias" value="tenant1sp"/>
              <property name="local" value="true"/>
            </bean>
          </argument>
        </bean>
        <bean class="org.springframework.security.saml.Metadata.ExtendedMetadataDelegate">
          <argument>
            <bean class="org.opensaml.saml2.Metadata.provider.ResourceBackedMetadataProvider">
              <argument>
                <bean class="java.util.Timer"/>
              </argument>
              <argument>
                <bean factory-ref="spResourceFactoryTenant2" factory-method="factoryResource" />
              </argument>
              <property name="parserPool" ref="parserPool"/>
            </bean>
          </argument>
          <argument>
            <bean class="org.springframework.security.saml.Metadata.ExtendedMetadata">
              <property name="idpdiscoveryEnabled" value="${saml.discovery.idp.enabled}"/>
              <property name="requirelogoutRequestSigned" value="${ensure.incoming.logout.request.signed}"/>
              <property name="alias" value="tenant2sp"/>
              <property name="local" value="true"/>
            </bean>
          </argument>
        </bean>

        <!-- idp Metadata -->
        <bean class="org.springframework.security.saml.Metadata.ExtendedMetadataDelegate">
          <argument>
            <bean class="org.opensaml.saml2.Metadata.provider.ResourceBackedMetadataProvider">
              <argument>
                <bean class="java.util.Timer"/>
              </argument>
              <argument>
                <bean factory-ref="idpResourceFactoryTenant1" factory-method="factoryResource" />
              </argument>
              <property name="parserPool" ref="parserPool"/>
            </bean>
          </argument>
          <argument>
            <bean class="org.springframework.security.saml.Metadata.ExtendedMetadata">
              <property name="idpdiscoveryEnabled" value="${saml.discovery.idp.enabled}"/>
              <property name="requirelogoutRequestSigned" value="${ensure.outgoing.logout.request.signed}"/>
              <property name="requirelogoutResponseSigned" value="${ensure.outgoing.logout.response.signed}"/>
              <property name="alias" value="tenant1idp"/>
              <property name="local" value="true"/>
            </bean>
          </argument>
        </bean>
        <bean class="org.springframework.security.saml.Metadata.ExtendedMetadataDelegate">
          <argument>
            <bean class="org.opensaml.saml2.Metadata.provider.ResourceBackedMetadataProvider">
              <argument>
                <bean class="java.util.Timer"/>
              </argument>
              <argument>
                <bean factory-ref="idpResourceFactoryTenant2" factory-method="factoryResource" />
              </argument>
              <property name="parserPool" ref="parserPool"/>
            </bean>
          </argument>
          <argument>
            <bean class="org.springframework.security.saml.Metadata.ExtendedMetadata">
              <property name="idpdiscoveryEnabled" value="${saml.discovery.idp.enabled}"/>
              <property name="requirelogoutRequestSigned" value="${ensure.outgoing.logout.request.signed}"/>
              <property name="requirelogoutResponseSigned" value="${ensure.outgoing.logout.response.signed}"/>
              <property name="alias" value="tenant2idp"/>
              <property name="local" value="true"/>
            </bean>
          </argument>
        </bean>

      </list>
    </argument>
    <property name="keyManager" ref="keyManager" />
    <property name="defaultIDP" value="${saml.idp.url}" />
  </bean>

使用此配置,当我转到url时 https://my.application.com/pentaho/alias/tenant1sp/sp?idp=tenant.1.name 我被重定向到IDP公开的tenant1登录页面登录后,我被重定向到上一个URL,得到一个一般错误see the screenshot

对不起,出了点问题。 请重试或联系 您的系统管理员

如果我转到URL https://my.application.com/pentaho/Home,我将登录到Pentaho仪表板。这使我认为登录过程已经成功,但是在流程结束时重定向出现了问题。实际上,我希望将其重定向到URL https://my.application.com/pentaho/Home我可以在某处/以某种方式配置此重定向吗?

解决方法

一种变通方法似乎可以解决此问题,但是我发现在使用Pentaho的公开API时,它与SAML身份验证产生了冲突。要使用这些API,此解决方案不好。


周围的工作


更改 successRedirectHandler bean的 defaultTargetUrl alwaysUseDefaultTargetUrl 属性(在的 blueprint.xml 文件中声明) Pentaho-SAML插件)

  <!-- Handler deciding where to redirect user after successful login -->
  <bean id="successRedirectHandler" class="org.pentaho.platform.spring.security.saml.PentahoSamlAuthenticationSuccessHandler" 
                        init-method="afterPropertiesSet">
    <property name="defaultTargetUrl" value="https://my.application.com/pentaho/Home"/>
    <property name="alwaysUseDefaultTargetUrl" value="true"/>
    <property name="requireProxyWrapping" value="false"/>
  </bean>

编辑:解决API登录问题 我使用自定义类扩展了 org.pentaho.platform.spring.security.saml.PentahoSamlAuthenticationSuccessHandler 类,该类重写了 onAuthenticationSuccess 方法

private String contextPath;

@Override
public void onAuthenticationSuccess(HttpServletRequest request,HttpServletResponse response,Authentication authentication) throws ServletException,IOException {

    SavedRequest savedRequest = requestCache.getRequest(request,response);
    
    //Apply the redirect to the Pentaho console Home if and only if the original targetUrl is not a Pentaho exposed API but the home (contextPath/Home)
    if (!savedRequest.getRedirectUrl().contains("API")
            && savedRequest.getRedirectUrl().contains(contextPath+"/Home")) {
        
        //The Pentaho console Home is set as defaultTargetUrl in the blueprint.xml
        this.setAlwaysUseDefaultTargetUrl(true);
        log.info("The request is not on a Pentaho API. Forcing the target URL to redirect to the defaultTargetUrl");
    }
    super.onAuthenticationSuccess(request,response,authentication);
    
    //retore the original value of alwaysUseDefaultTargetUrl
    this.setAlwaysUseDefaultTargetUrl(false);
}

相关问答

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