2016-01-27 3 views
0

Я пытаюсь адаптировать Spring Security SAML sample application, чтобы использовать тестовый IDP (предоставленный мне кем-то другим) вместо ssocircle. Нажатие на «Логин SAML» правильно перенаправляет меня на страницу входа в систему единого входа IDP, но после входа в систему и перенаправления обратно к образцу приложения я получаю исключение (видимо, во время разрешения артефакта), корень которого:Spring Security SAML - как настроить клиентскую аутентификацию?

org.opensaml.ws.message.decoder.MessageDecodingException: Error when sending request to artifact resolution service. 
    at org.springframework.security.saml.websso.ArtifactResolutionProfileImpl.getArtifactResponse(ArtifactResolutionProfileImpl.java:110) 
    at org.springframework.security.saml.websso.ArtifactResolutionProfileBase.resolveArtifact(ArtifactResolutionProfileBase.java:101) 
    ... 34 more 
Caused by: javax.net.ssl.SSLPeerUnverifiedException: SSL peer failed hostname validation for name: null 
    at org.opensaml.ws.soap.client.http.TLSProtocolSocketFactory.verifyHostname(TLSProtocolSocketFactory.java:233) 
    at org.opensaml.ws.soap.client.http.TLSProtocolSocketFactory.createSocket(TLSProtocolSocketFactory.java:186) 
    at org.apache.commons.httpclient.HttpConnection.open(HttpConnection.java:707) 
    at org.apache.commons.httpclient.MultiThreadedHttpConnectionManager$HttpConnectionAdapter.open(MultiThreadedHttpConnectionManager.java:1361) 
    at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:387) 
    at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:171) 
    at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397) 
    at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:346) 
    at org.springframework.security.saml.websso.ArtifactResolutionProfileImpl.getArtifactResponse(ArtifactResolutionProfileImpl.java:99) 

После копания какое-то время я понял, что сервер ожидает аутентификации клиента в соответствующем порту. Если подключить к нему, как это, я получаю правильный ответ:

curl -k --cert spcert.pem --key spkey.pem https://testidp:8110/idp/profile/SAML2/SOAP/ArtifactResolution 

Кроме того, исключение уходит, если отключить clientAuth на IDP пути редактирования server.x МВОЙ кота и изменений clientAuth к «ложной» в соответствующем теге <Connector>.

Подключение к порту ВПЛ 8110 отлично работает, если я использую Apache HttpClient как так

package at.awst.perkele.httpstest; 

import java.io.BufferedReader; 
import java.io.FileInputStream; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.security.KeyManagementException; 
import java.security.KeyStore; 
import java.security.KeyStoreException; 
import java.security.NoSuchAlgorithmException; 
import java.security.UnrecoverableKeyException; 
import java.security.cert.CertificateException; 

import javax.net.ssl.SSLContext; 

import org.apache.http.HttpEntity; 
import org.apache.http.client.methods.CloseableHttpResponse; 
import org.apache.http.client.methods.HttpGet; 
import org.apache.http.conn.ssl.SSLConnectionSocketFactory; 
import org.apache.http.conn.ssl.TrustSelfSignedStrategy; 
import org.apache.http.impl.client.CloseableHttpClient; 
import org.apache.http.impl.client.HttpClients; 
import org.apache.http.ssl.SSLContexts; 
import org.apache.http.util.EntityUtils; 

public class HTTPSTest { 
    private static final String CA_KEYSTORE_TYPE = KeyStore.getDefaultType(); // "JKS"; 
    private static final String CA_KEYSTORE_PATH = "myKeystore.jks"; 
    private static final String CA_KEYSTORE_PASS = "secret"; 

    private static final String CLIENT_KEYSTORE_TYPE = KeyStore.getDefaultType(); // "JKS"; 
    private static final String CLIENT_KEYSTORE_PATH = "myKeystore.jks"; 
    private static final String CLIENT_KEYSTORE_PASS = "secret"; 

    private static final String HTTPS_URL = "https://testidp:8110/idp/profile/SAML2/SOAP/ArtifactResolution"; 

    public static void main(String[] args) throws Exception { 
     SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(createSslCustomContext(), new String[] { "TLSv1" }, 
       null, SSLConnectionSocketFactory.getDefaultHostnameVerifier()); 

     try (CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(csf).build()) { 
      HttpGet req = new HttpGet(HTTPS_URL); 
      try (CloseableHttpResponse response = httpclient.execute(req)) { 
       HttpEntity entity = response.getEntity(); 

       System.out.println(String.format("Reponse status: %s", response.getStatusLine())); 
       System.out.println(String.format("Response entity: %s", entity.toString())); 

       BufferedReader in = new BufferedReader(new InputStreamReader(entity.getContent())); 
       String line = null; 
       while ((line = in.readLine()) != null) { 
        System.out.println(line); 
       } 
       EntityUtils.consume(entity); 
      } 
     } 
    } 

    private static SSLContext createSslCustomContext() throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, KeyManagementException, UnrecoverableKeyException { 
     // Trusted CA keystore 
     KeyStore tks = KeyStore.getInstance(CA_KEYSTORE_TYPE); 
     tks.load(new FileInputStream(CA_KEYSTORE_PATH), CA_KEYSTORE_PASS.toCharArray()); 

     // Client keystore 
     KeyStore cks = KeyStore.getInstance(CLIENT_KEYSTORE_TYPE); 
     cks.load(new FileInputStream(CLIENT_KEYSTORE_PATH), CLIENT_KEYSTORE_PASS.toCharArray()); 

     SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(tks, new TrustSelfSignedStrategy()) 
       .loadKeyMaterial(cks, CLIENT_KEYSTORE_PASS.toCharArray()) 
       .build(); 
     return sslcontext; 
    } 

} 

Однако, я не знаю, как правильно настроить TLSProtocolConfigurer Spring SAML (или все, что необходимо использовать клиент ключ).

Итак, как я могу сообщить SAML Spring Security использовать мой клиентский ключ для аутентификации клиента в соединениях TLS/SSL?

+0

Предоставьте свой securityContext.xml. Также вы импортировали сертификат своего тестового IDP? –

+0

Я добавил его к вопросу. Да, я импортировал сертификат IDP в мое хранилище ключей (настроено в securityContext.xml). BTW: Если я переключу clientAuth с true на false в IDP (путем редактирования server.xml и изменения ''), пример приложения начинает работать. – Ginkobonsai

ответ

1

ОК, выяснили, как включить clientAuth в соединениях TLS для Spring SAML. Это мой провайдер конфигурации из securityContext.xml:

<bean class="org.springframework.security.saml.metadata.ExtendedMetadataDelegate"> 
    <constructor-arg> 
     <bean class="org.opensaml.saml2.metadata.provider.FilesystemMetadataProvider"> 
      <constructor-arg> 
       <value type="java.io.File">classpath:metadata/sp.xml</value> 
      </constructor-arg> 
      <property name="parserPool" ref="parserPool" /> 
     </bean> 
    </constructor-arg> 
    <constructor-arg> 
     <bean class="org.springframework.security.saml.metadata.ExtendedMetadata"> 
      <property name="local" value="true" /> 
      <property name="signMetadata" value="true" /> 
      <property name="signingKey" value="mykey" /> 
      <property name="encryptionKey" value="mykey" /> 
      <property name="tlsKey" value="mykey" /> 
     </bean> 
    </constructor-arg> 
</bean> 

ClientAuth включена, установив ключ клиента с помощью <property name="tlsKey" value="mykey" />

Ключ должен быть объявлен в JKSKeyManager как обычно:

<bean id="keyManager" class="org.springframework.security.saml.key.JKSKeyManager"> 
    <constructor-arg value="classpath:security/keystore.jks" /> 
    <constructor-arg type="java.lang.String" value="secret" /> 
    <constructor-arg> 
     <map> 
      <entry key="mykey" value="secret" /> 
     </map> 
    </constructor-arg> 
    <constructor-arg type="java.lang.String" value="mykey" /> 
</bean> 

Это mentioned in the docs here как «Заполнение учетных данных, используемых для аутентификации клиентов SSL/TLS. В случае, если ExtendedMetadata указывает свойство tlsKey, он будет использоваться как псевдоним для поиска ключа из bean keyManager. В противном случае нет credenti al будет предоставлена ​​для аутентификации клиента ». Понадобилось время, чтобы найти это ;-)

Смежные вопросы