복붙노트

[SPRING] 봄 SAML - 읽기 및 실행시 상쾌한 IdP가 메타 데이터

SPRING

봄 SAML - 읽기 및 실행시 상쾌한 IdP가 메타 데이터

나는 봄 - SAML 확장자 WSO2과 SSOCircle을 사용하고 있습니다. 우리는이 시점에서 구성을 테스트하는 우리의 ApplicationContext 내에서 2 개 IdP가의 2 SP의를 정의했습니다. 그래서, 현재, 우리는 우리의 스프링의 XML 설정 내에서이 개 정적으로 정의 IdP 구성의이이 노력하고 있습니다. 테스트 목적을 위해 우리는 IdP가 메타 데이터가 우리의 WAR 아카이브의 내부에 내장되도록 CachingMetadataManager 및 ResourceBackedMetadataProvider의 조합을 사용하고 있습니다. 견본:

<bean id="metadata" class="org.springframework.security.saml.metadata.CachingMetadataManager">
<constructor-arg>
  <list>
    <bean class="org.springframework.security.saml.metadata.ExtendedMetadataDelegate">
      <constructor-arg>
        <bean class="org.opensaml.saml2.metadata.provider.ResourceBackedMetadataProvider">
          <constructor-arg>
            <bean class="java.util.Timer"/>
          </constructor-arg>
          <constructor-arg>
            <bean class="org.opensaml.util.resource.ClasspathResource">
              <constructor-arg value="/metadata/wso2idp_metadata.xml"/>
            </bean>
          </constructor-arg>
          <property name="parserPool" ref="parserPool"/>
        </bean>
      </constructor-arg>
      <constructor-arg>
        <bean class="org.springframework.security.saml.metadata.ExtendedMetadata">
        </bean>
      </constructor-arg>
    </bean>
    <bean class="org.springframework.security.saml.metadata.ExtendedMetadataDelegate">
      <constructor-arg>
        <bean class="org.opensaml.saml2.metadata.provider.ResourceBackedMetadataProvider">
          <constructor-arg>
            <bean class="java.util.Timer"/>
          </constructor-arg>
          <constructor-arg>
            <bean class="org.opensaml.util.resource.ClasspathResource">
              <constructor-arg value="/metadata/ssocircleidp_metadata.xml"/>
            </bean>
          </constructor-arg>
          <property name="parserPool" ref="parserPool"/>
        </bean>
      </constructor-arg>
      <constructor-arg>
        <bean class="org.springframework.security.saml.metadata.ExtendedMetadata">
        </bean>
      </constructor-arg>
    </bean>
  </list>
</constructor-arg>

생산을 위해, 우리는 (중앙에 위치) 데이터베이스에 우리의 IdP가 메타 데이터를 저장할 수 있어야합니다. 나는 WAR을 다시 배포 또는 서버 (들)을 다시 시작하지 않고 메타 데이터를 추가, 제거 및 수정할 수 있어야합니다. 처음에 나는이 CachingMetadataManager을 무시하고 동적으로 모든 메타 데이터 공급자를로드 할 수있는 noarg 생성자를 정의 할 수 있다고 생각하지만, CachingMetadataManager 만 MetadataProvider 목록에 취해야 하나의 생성자를 정의하기 때문에이 불가능합니다. 나는 다음을 수행 결국 :

<bean id="metadataList" class="org.arbfile.util.security.saml.DBMetadataProviderList">
  <constructor-arg ref="parserPool" />
  <constructor-arg>
    <bean class="java.util.Timer"/>
  </constructor-arg>
</bean>

<bean id="metadata" class="org.springframework.security.saml.metadata.CachingMetadataManager">
   <constructor-arg ref="metadataList" />
</bean>

콩 metadataList은 간단하게 정의 할 수 있습니다 :

public final class DBMetadataProviderList extends ArrayList<MetadataProvider>
{
  private final static Logger log = LoggerFactory.getLogger(DBMetadataProviderList.class);
  private ParserPool parser;

  public DBMetadataProviderList(ParserPool _parser, Timer _timer) throws MetadataProviderException
  {
    this.parser = _parser;
// Lookup metadata from DB
  }

}

이 날은 동적으로 IdP가 메타 데이터에 읽을 수 없습니다. 그것이 비록 새로 고침 할 때 내 논리는 아래로 떨어진다. 그러나 나는 그것이 3 ~ 4 세이며, 봄 포럼에서 해당 게시물을 발견했다. 동적 IdP가 메타 데이터, 캐시를 추가하고, 읽고 업데이트하는 가장 좋은 방법은 무엇입니까 그것은 어떤 간격으로 캐시 새로 고침이? DB를 테이블에 내 경우 1 행에 하나의 IdP가 메타 데이터 정의에 달합니다.

해결법

  1. ==============================

    1.여러 게시물을 읽고 소스 코드를 스캔 후, 나는이 질문에 대한 대답은 내가 생각했던 것보다 더 복잡하다 발견했다. 해결하기 위해 정말 3 개 가지 시나리오가 있습니다.

    여러 게시물을 읽고 소스 코드를 스캔 후, 나는이 질문에 대한 대답은 내가 생각했던 것보다 더 복잡하다 발견했다. 해결하기 위해 정말 3 개 가지 시나리오가 있습니다.

    나는 한 번에이 하나의 각에 걸릴 수 있습니다. 항목 1 : 아마 신속하고 더러운 솔루션으로이 문제를 해결하지만, 검토 (내 영업 이익)이 DBMetadataProviderList 클래스를 위의 방법에는 여러 가지가 있습니다. 여기에 더 완전한 생성자 코드는 다음과 같습니다

    //This constructor allows us to read in metadata stored in a database. 
    public DBMetadataProviderList(ParserPool _parser, Timer _timer) throws MetadataProviderException
    {
        this.parser = _parser;
        List<String> metadataProviderIds = getUniqueEntityIdListFromDB();
        for (final String mdprovId : metadataProviderIds)
        {
            DBMetadataProvider metadataProvider = new DBMetadataProvider(_timer, mdprovId);
            metadataProvider.setParserPool(this.parser);
            metadataProvider.setMaxRefreshDelay(480000); // 8 mins (set low for testing)
            metadataProvider.setMinRefreshDelay(120000); // 2 mins
            ExtendedMetadataDelegate md = new ExtendedMetadataDelegate(metadataProvider,  new ExtendedMetadata());
            add(md);
        }
    }
    

    2 번 항목을 해결하기 위해 나는 가이드로 FilesystemMetadataProvider을 사용하고 DBMetadataProvider 클래스를 만들었습니다. AbstractReloadingMetadataProvider 클래스를 확장하고 우리가 내장되어 opensaml 감사는 상쾌한 캐시 fetchMetadata () 메소드를 구현함으로써. 아래는 중요한 부분 (예를 들어, 코드에만 해당)입니다 :

    public class DBMetadataProvider extends AbstractReloadingMetadataProvider
    {
      private String metaDataEntityId;  // unique Id for DB lookups
    
     /**
      * Constructor.
      * @param entityId the entity Id of the metadata.  Use as key to identify a database row.
      */
     public DBMetadataProvider(String entityId)
     {
        super();
        setMetaDataEntityId(entityId);
     }
    
     /**
      * Constructor.
      * @param backgroundTaskTimer timer used to refresh metadata in the background
      * @param entityId the entity Id of the metadata.  Use as key to identify a database row.
      */
     public DBMetadataProvider(Timer backgroundTaskTimer, String entityId)
     {
        super(backgroundTaskTimer);
        setMetaDataEntityId(entityId);
     }
    
     public String getMetaDataEntityId() { return metaDataEntityId;  }
    
     public void setMetaDataEntityId(String metaDataEntityId){ this.metaDataEntityId = metaDataEntityId; }
    
     @Override
     protected String getMetadataIdentifier() { return getMetaDataEntityId(); }
    
    // This example code simply does straight JDBC
     @Override
     protected byte[] fetchMetadata() throws MetadataProviderException
     {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try
        {
            conn = JDBCUtility.getConnection();
            ps = conn.prepareStatement("select  bla bla bla ENTITY_ID = ?");
            ps.setString(1, getMetaDataEntityId());
            rs = ps.executeQuery();
            if (rs.next())
            {
                // include a modified date column in schema so that we know if row has changed
                Timestamp sqldt = rs.getTimestamp("MOD_DATE"); // use TimeStamp here to get full datetime
                DateTime metadataUpdateTime = new DateTime(sqldt.getTime(), ISOChronology.getInstanceUTC());
                if (getLastRefresh() == null || getLastUpdate() == null || metadataUpdateTime.isAfter(getLastRefresh()))
                {
                    log.info("Reading IdP metadata from database with entityId = " + getMetaDataEntityId());
                    Clob clob = rs.getClob("XML_IDP_METADATA");
                    return clob2Bytes(clob);
                }
                return null;
            }
            else
            {
                // row was not found
                throw new MetadataProviderException("Metadata with entityId = '" + getMetaDataEntityId() + "' does not exist");
            }
        }
        catch (Exception e)
        {
            String msg = "Unable to query metadata from database with entityId = " + getMetaDataEntityId();
            log.error(msg, e);
            throw new MetadataProviderException(msg, e);
        }
        finally
        {
            // clean up connections
        }
      }
    
     }
    

    이 자원은 나를 캐시 다시로드 메타 데이터 프로 바이더 클래스에 맞는 기술을 회복했습니다. 마지막으로, 항목 # 3이 게시물을 구현하여 해결할 수 있습니다.

  2. from https://stackoverflow.com/questions/42906985/spring-saml-reading-and-refreshing-idp-metadata-at-runtime by cc-by-sa and MIT license