Я разрабатываю мыльный веб-сервис на основе 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
5UY+qVbnzYltP0Do+QuWqrGrQtQtrcugOxuATMIJkR5CTYuJ4j6/FzeeW7PvQKw78H/mXOWdN+Uz
hjmmcDKSqvwy49c8SqFl8f9xcjBsz2Mz6HQ0P/JnDGKX39XgPFFLW1NJCdF4ENmZAYmGZ0evp4Ym
rXF2NtyjZz18rrHrVY8CsLB7XdokPM3iNtH1nD/qeLmJnHN6xaH6UJBAeJQI4FEOe5aM/5clL/5t
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, чтобы получить все содержащиеся в нем атрибуты.
Заранее спасибо.