Получить принципал из утверждения SAML в SOAP Spring-Security-WS - PullRequest
0 голосов
/ 07 сентября 2018

Я разрабатываю мыльный веб-сервис на основе spring-security-ws .И я хочу защитить входящие запросы мыла с помощью токена SAML.

Итак, на стороне сервера я написал этот код:

    import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.ws.config.annotation.EnableWs;
import org.springframework.ws.config.annotation.WsConfigurerAdapter;
import org.springframework.ws.server.EndpointInterceptor;
import org.springframework.ws.soap.security.wss4j2.Wss4jSecurityInterceptor;
import org.springframework.ws.soap.security.wss4j2.callback.KeyStoreCallbackHandler;
import org.springframework.ws.soap.security.wss4j2.support.CryptoFactoryBean;
import org.springframework.ws.transport.http.MessageDispatcherServlet;
import org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition;
import org.springframework.xml.xsd.SimpleXsdSchema;
import org.springframework.xml.xsd.XsdSchema;

import java.util.List;

@EnableWs
@Configuration
public class WebServiceConfig extends WsConfigurerAdapter {

    @Bean
    public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
        MessageDispatcherServlet servlet = new MessageDispatcherServlet();
        servlet.setApplicationContext(applicationContext);
        servlet.setTransformWsdlLocations(true);
        return new ServletRegistrationBean(servlet, "/ws/*");
    }

    @Bean(name = "echo-request")
    public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema echoRequestSchema) {
        DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
        wsdl11Definition.setPortTypeName("EchoRequestPortType");
        wsdl11Definition.setLocationUri("/ws");
        wsdl11Definition.setTargetNamespace("http://lu.etat.ada.luccs.services.soap");
        wsdl11Definition.setSchema(echoRequestSchema);
        return wsdl11Definition;
    }

    @Bean
    public XsdSchema echoRequestSchema() {
        return new SimpleXsdSchema(new ClassPathResource("echo-request.xsd"));
    }

    @Bean
    Wss4jSecurityInterceptor securityInterceptor() throws Exception {
        Wss4jSecurityInterceptor securityInterceptor = new Wss4jSecurityInterceptor();

        securityInterceptor.setValidationActions("Timestamp SAMLTokenSigned Signature");
        securityInterceptor.setValidationSignatureCrypto(signature().getObject());
        securityInterceptor.setValidationCallbackHandler(securityCallbackHandler());

        return securityInterceptor;
    }

    @Bean
    public KeyStoreCallbackHandler securityCallbackHandler() {
        KeyStoreCallbackHandler callbackHandler = new KeyStoreCallbackHandler();
        callbackHandler.setPrivateKeyPassword("password");
        return callbackHandler;
    }

    @Bean
    CryptoFactoryBean signature() throws Exception {
        CryptoFactoryBean cryptoFactoryBean = new CryptoFactoryBean();
        cryptoFactoryBean.setKeyStorePassword("password");
        //cryptoFactoryBean.setDefaultX509Alias("mykey");
        cryptoFactoryBean.setKeyStoreLocation(new ClassPathResource("keystore.jks"));
        return cryptoFactoryBean;
    }

    @Override
    public void addInterceptors(List<EndpointInterceptor> interceptors) {
        try {
            interceptors.add(securityInterceptor());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

И моя конечная точка следующая:

import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
import org.springframework.ws.server.endpoint.annotation.RequestPayload;
import org.springframework.ws.server.endpoint.annotation.ResponsePayload;
import org.springframework.ws.soap.SoapHeaderElement;
import org.springframework.ws.soap.server.endpoint.annotation.SoapHeader;
import soap.services.luccs.ada.etat.lu.GetEchoRequest;
import soap.services.luccs.ada.etat.lu.GetEchoResponse;
import soap.services.luccs.ada.etat.lu.GetHeader;
import soap.services.luccs.ada.etat.lu.ObjectFactory;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;


@Endpoint
public class RequestEndpoint {

    private static final String NAMESPACE_URI = "http://lu.etat.ada.luccs.services.soap";

    @PayloadRoot(namespace = NAMESPACE_URI, localPart = "getEchoRequest")
    @ResponsePayload
    public GetEchoResponse getEchoResponse(@RequestPayload GetEchoRequest getEchoRequest,
                                           @SoapHeader(
                                                   value = "{" + NAMESPACE_URI + "}getHeader") SoapHeaderElement soapHeaderElement, org.springframework.ws.soap.SoapHeader soapHeader
                                           , MessageContext messageContext
                                           ) throws Exception {
        GetEchoResponse getEchoResponse = new GetEchoResponse();

        // create an unmarshaller
        JAXBContext context = JAXBContext.newInstance(ObjectFactory.class);
        Unmarshaller unmarshaller = context.createUnmarshaller();

        if (soapHeaderElement != null) {
            // unmarshal the header from the specified source
            GetHeader getHeader = (GetHeader) unmarshaller.unmarshal(soapHeaderElement.getSource());

            getEchoResponse.setHeader(getHeader.getHeader());
        }

        getEchoResponse.setBody(getEchoRequest.getBody());

        SecurityContext securityContext = SecurityContextHolder.getContext();
        System.out.println("securityContext.getAuthentication(): " + securityContext.getAuthentication());

        System.out.println("messageContext: " + messageContext);
        System.out.println("messageContext property names length: " + messageContext.getPropertyNames().length);

        return getEchoResponse;
    }

На стороне клиента я использую SOAP UI для выполнения запроса мыла, в котором я помещаю утверждение SAML в головное устройство следующим образом:

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:lu="http://lu.etat.ada.luccs.services.soap">
   <soapenv:Header>
      <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
         <wsse:BinarySecurityToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" wsu:Id="_3adb63447af408c6ad0d64570861ad9d">MIIDazCCAlOgAwIBAgIEdhifQjANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQGEwJldTEQMA4GA1UECBMHVW5rbm93bjEQMA4GA1UEBxMHVW5rbm93bjELMAkGA1UEChMCZWMxETAPBgNVBAsTCGN1c3RkZXYzMRIwEAYDVQQDEwljY24yIG1vY2swIBcNMTYwOTIzMTI1MzQ1WhgPMjExNjA4MzAxMjUzNDVaMGUxCzAJBgNVBAYTAmV1MRAwDgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdVbmtub3duMQswCQYDVQQKEwJlYzERMA8GA1UECxMIY3VzdGRldjMxEjAQBgNVBAMTCWNjbjIgbW9jazCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJEZNCwaLcuzHnK9fnPyA3hUnCvtgzGZ6Fj7thwc6Kr78yhOHvuE96xJFfxwvriIQ2S1KPJQ+A1hoTysQ1ZlZSWWeRbYQPVRdHe0wN/D/8a3dYijdqO+NUzOkXczdy+lKmvFRPULfBtlW/KTSLKswCp0QASOLfVgXgv2YkNyRSZizCUfZ8cvkm8l5sppxaTapPJ48LBqMQGsnoKRtwrFbjZkM/B9nJaFXMHAv0w/CqHXQ1kePJZnn/0IFaPNbRpE+gHxJ9IjKLvGJ+bTwEBlZlYtOsLiXDSZI1ohUW37bbzBMFHv4J+EX0X89Uvu7kJdfou5AS6D0KHC38KK6XmNLWsCAwEAAaMhMB8wHQYDVR0OBBYEFKhoWoACAY65G//jz51mjugU1OZUMA0GCSqGSIb3DQEBCwUAA4IBAQAlS23BIVhuPpeEOmAABNMVYfuA/lEDmpyRDuA3z9uuX3hHn/ME1fR71z9IFl4cjiiq7Ua+7loee5Lr69bsoX75bWSeV5pmHSyc4reObcnSkz8Ro2XS5UEtP9Ym5U6Zp9Ytr2k+QV5mRNj0CTYRzcUltvRHrr0K2QagUHb6EEll5KSkvpO30VZfFN9TsalBX2aXpimiFNjpTRQM4rYPuiBvSvYDoeu7+xS2WktXHC9szWXLV8Z2GyRYPDYAEtrL2cM3qZWWKpHE8NgMzzuiInjc7gcdhDjej+mcsizsXIoUMwIwZ1DW80FkdqvzeW64Bq2Oik0MlSVjH2q9VR7g4leI</wsse:BinarySecurityToken>
         <saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="_d2ab7571af560c041bc90ba110ea2bc0" IssueInstant="2018-08-29T13:08:47.322Z" Version="2.0">
            <saml2:Issuer Format="urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName">CN=ccn2 mock,OU=custdev3,O=ec,L=Unknown,ST=Unknown,C=eu</saml2:Issuer>
            <saml2:Subject>
               <saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">tatafng.tests2s</saml2:NameID>
               <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:sender-vouches" />
            </saml2:Subject>
            <saml2:Conditions NotBefore="2018-08-29T13:07:47.322Z" NotOnOrAfter="2018-08-29T13:13:47.322Z" />
            <saml2:AuthnStatement AuthnInstant="2018-08-29T13:08:47.322Z">
               <saml2:AuthnContext>
                  <saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml2:AuthnContextClassRef>
               </saml2:AuthnContext>
            </saml2:AuthnStatement>
            <saml2:AttributeStatement>
               <saml2:Attribute Name="uid" NameFormat="urn:vordel:attribute:1.0">
                  <saml2:AttributeValue>tatafng.tests2s</saml2:AttributeValue>
               </saml2:Attribute>
               <saml2:Attribute Name="partnername" NameFormat="urn:vordel:attribute:1.0">
                  <saml2:AttributeValue>CCN2.Partner.LU.Customs.Default</saml2:AttributeValue>
               </saml2:Attribute>
               <saml2:Attribute Name="c" NameFormat="urn:vordel:attribute:1.0">
                  <saml2:AttributeValue>LU</saml2:AttributeValue>
               </saml2:Attribute>
               <saml2:Attribute Name="role" NameFormat="urn:vordel:attribute:1.0">
                  <saml2:AttributeValue>roleA</saml2:AttributeValue>
                  <saml2:AttributeValue>roleB</saml2:AttributeValue>
               </saml2:Attribute>
            </saml2:AttributeStatement>
         </saml2:Assertion>
         <wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="_7bc08bc16a832ed527dfccef7483320c">
            <wsu:Created>2018-08-29T13:07:47.323Z</wsu:Created>
            <wsu:Expires>2018-08-29T13:13:47.323Z</wsu:Expires>
         </wsu:Timestamp>
         <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
            <ds:SignedInfo>
               <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
               <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
               <ds:Reference URI="#_3adb63447af408c6ad0d64570861ad9d">
                  <ds:Transforms>
                     <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
                  </ds:Transforms>
                  <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
                  <ds:DigestValue>o0h5aUG4avjIPDd/P/kdfXIGkx0UWPXnAGVJ1pF587A=</ds:DigestValue>
               </ds:Reference>
               <ds:Reference URI="#_d2ab7571af560c041bc90ba110ea2bc0">
                  <ds:Transforms>
                     <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
                  </ds:Transforms>
                  <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
                  <ds:DigestValue>pTi9Vw7Gq7HJZjiYTO0rQ/8xYcfxH0Y9skI9pP2yrXs=</ds:DigestValue>
               </ds:Reference>
               <ds:Reference URI="#_7bc08bc16a832ed527dfccef7483320c">
                  <ds:Transforms>
                     <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
                  </ds:Transforms>
                  <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
                  <ds:DigestValue>htZB1NN3dlGDmuRels9vvFpUYWa5XWq4nDGyiQUaqoQ=</ds:DigestValue>
               </ds:Reference>
            </ds:SignedInfo>
            <ds:SignatureValue>jOHsJLelLFt1ZwqhTbXPVmypV0L8vTVFxOOr2rUwYahiRdyvrmyp7baMBMP6f2Fz9Q2MFIbEdQHV&#xD;
5UY+qVbnzYltP0Do+QuWqrGrQtQtrcugOxuATMIJkR5CTYuJ4j6/FzeeW7PvQKw78H/mXOWdN+Uz&#xD;
hjmmcDKSqvwy49c8SqFl8f9xcjBsz2Mz6HQ0P/JnDGKX39XgPFFLW1NJCdF4ENmZAYmGZ0evp4Ym&#xD;
rXF2NtyjZz18rrHrVY8CsLB7XdokPM3iNtH1nD/qeLmJnHN6xaH6UJBAeJQI4FEOe5aM/5clL/5t&#xD;
LEoJkeApNJYr+o8/hAXySDIprWK+LjG1scABKQ==</ds:SignatureValue>
            <ds:KeyInfo Id="_49c62035be0068ccd99168c1f1b325e2">
               <wsse:SecurityTokenReference xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="_f3dcdb7de73167f8deefa50487adad2d">
                  <wsse:Reference URI="#_3adb63447af408c6ad0d64570861ad9d" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" />
               </wsse:SecurityTokenReference>
            </ds:KeyInfo>
         </ds:Signature>
      </wsse:Security>
   </soapenv:Header>
   <soapenv:Body>
      <lu:getEchoRequest>
         <lu:body>
            <lu:message>message body</lu:message>
         </lu:body>
      </lu:getEchoRequest>
   </soapenv:Body>
</soapenv:Envelope>

Все работает, но теперь мне нужно получитьпринципал из утверждения SAML для получения некоторой информации (NAMEID, атрибуты SAML, ...).ТАК к моей конечной точке метода я вставляю MessageContext , чтобы получить некоторую информацию из сообщения SOAP, но я не знаю, как поступить, так как нет атрибутов?Я также пытался получить Аутентификацию, но она возвращает ноль.

SecurityContext securityContext = SecurityContextHolder.getContext();
    System.out.println("securityContext.getAuthentication(): " + securityContext.getAuthentication()); // null

System.out.println("messageContext: " + messageContext); // not null
System.out.println("messageContext property names length: " + messageContext.getPropertyNames().length); // 0

Я нашел так много примеров для служб REST, где вы расширяете свою конфигурацию из WebSecurityConfigurerAdapter, и вы можете переопределить SAMLAuthenticationProvider и внедрить компонент в метод конфигурации.Но все это связано со службой REST, и я разрабатываю службу SOAP .

Кто-нибудь может мне помочь?

PS: Может быть, вы можете защитить службу SOAP в другихно мне нужно использовать Spring и инициализировать некоторый контекст безопасности или аутентификацию из утверждения SAML, чтобы получить все содержащиеся в нем атрибуты.

Заранее спасибо.

...