Spring Boot:在基于Web服务安全性(WS-Security,WSS)用户名的SOAP请求中添加特定的HTTP标头

问题描述 投票:0回答:1

我正在使用Spring Boot公开SOAP Web服务。此Web服务使用Web Service安全性(WSS)进行保护,该Web服务安全性是使用<< security_policy.xml:

配置的<xwss:SecurityConfiguration xmlns:xwss="http://java.sun.com/xml/ns/xwss/config"> <xwss:RequireUsernameToken passwordDigestRequired="true" nonceRequired="true" /> </xwss:SecurityConfiguration>
直到这一点,应用程序运行正常。它能够成功进行身份验证。

现在,我需要基于WSS用户名添加特定的HTTP标头。也就是说,在HTTP标头

“ x-auth-type”

中添加以下值:
  • “ test-auth-type”
当用户名是“ test”
  • “ production-auth-type”
  • 当用户名是“ production”
  • “ undefined-auth-type”
  • 否则

    我以为添加EndpointInterceptor很容易,在其中可以基于用户设置HTTP标头,但直到现在我还是无法实现。

    我的Web服务配置类如下:

    package com.godev.soapwebserviceswithspring; import java.util.Collections; import java.util.List; 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.server.endpoint.interceptor.PayloadLoggingInterceptor; import org.springframework.ws.soap.security.xwss.XwsSecurityInterceptor; import org.springframework.ws.soap.security.xwss.callback.SimplePasswordValidationCallbackHandler; import org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor; 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; @EnableWs @Configuration public class WebServiceConfig extends WsConfigurerAdapter { private static final String WS_SCHEMA_PATH = "godev_contract.xsd"; private static final String NAMESPACE_URI = "http://godev.com/soap/webservices/demo"; @Bean public ServletRegistrationBean<MessageDispatcherServlet> messageDispatcherServlet( ApplicationContext applicationContext) { MessageDispatcherServlet servlet = new MessageDispatcherServlet(); servlet.setApplicationContext(applicationContext); servlet.setTransformWsdlLocations(true); return new ServletRegistrationBean<>(servlet, "/ws/*"); } @Bean(name = "xml_message") public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema billsSchema) { DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition(); wsdl11Definition.setPortTypeName("XmlMessagePort"); wsdl11Definition.setLocationUri("/ws"); wsdl11Definition.setTargetNamespace(NAMESPACE_URI); wsdl11Definition.setSchema(billsSchema); return wsdl11Definition; } @Bean public XsdSchema countriesSchema() { return new SimpleXsdSchema(new ClassPathResource(WS_SCHEMA_PATH)); } @Bean PayloadLoggingInterceptor payloadLoggingInterceptor() { return new PayloadLoggingInterceptor(); } @Bean PayloadValidatingInterceptor payloadValidatingInterceptor() { final PayloadValidatingInterceptor payloadValidatingInterceptor = new PayloadValidatingInterceptor(); payloadValidatingInterceptor.setSchema(new ClassPathResource(WS_SCHEMA_PATH)); return payloadValidatingInterceptor; } @Bean XwsSecurityInterceptor securityInterceptor() { XwsSecurityInterceptor securityInterceptor = new XwsSecurityInterceptor(); securityInterceptor.setCallbackHandler(callbackHandler()); securityInterceptor.setPolicyConfiguration(new ClassPathResource("security_policy.xml")); return securityInterceptor; } @Bean SimplePasswordValidationCallbackHandler callbackHandler() { SimplePasswordValidationCallbackHandler callbackHandler = new SimplePasswordValidationCallbackHandler(); callbackHandler.setUsersMap(Collections.singletonMap("admin", "pwd123")); return callbackHandler; } @Override public void addInterceptors(List<EndpointInterceptor> interceptors) { interceptors.add(payloadLoggingInterceptor()); interceptors.add(payloadValidatingInterceptor()); interceptors.add(securityInterceptor()); } }

    我的Web服务端点类看起来像这样:

    package com.godev.soapwebserviceswithspring; 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 com.godev.soap.webservices.demo.GetXmlMessageRequest; import com.godev.soap.webservices.demo.GetXmlMessageResponse; @Endpoint public class XmlMessageEndpoint { private static final String NAMESPACE_URI = "http://godev.com/soap/webservices/demo"; @PayloadRoot(namespace = NAMESPACE_URI, localPart = "getXmlMessageRequest") @ResponsePayload public GetXmlMessageResponse getXmlDocument(@RequestPayload GetXmlMessageRequest request) { GetXmlMessageResponse response = new GetXmlMessageResponse(); response.setXmlMessage("<xml>empty document</xml>"); return response; } }

    任何建议将不胜感激!
    spring-boot http soap spring-security spring-ws
    1个回答
    0
    投票
    它对我有用:

    Endpoint的SOAP头中注入Security元素:

    @Endpoint public class XmlMessageEndpoint { private static final String NAMESPACE_URI = "http://godev.com/soap/webservices/demo"; @PayloadRoot(namespace = NAMESPACE_URI, localPart = "getXmlMessageRequest") @ResponsePayload public GetXmlMessageResponse getXmlDocument(@RequestPayload GetXmlMessageRequest request, @SoapHeader("{" + Security.SECURITY_NAMESPACE + "}Security") SoapHeaderElement securityHeader) { GetXmlMessageResponse response = new GetXmlMessageResponse(); response.setXmlMessage("<xml>empty document</xml>"); return response; }
    为了将

    securityHeader

    解析为可用的东西,您需要定义几个POJO。就我而言,我只需要username

    用于安全元素的POJO

    @XmlAccessorType(XmlAccessType.FIELD) @XmlRootElement(namespace = Security.SECURITY_NAMESPACE, name = "Security") @Getter @Setter public class Security { public static final String SECURITY_NAMESPACE = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"; @XmlElement(namespace = Security.SECURITY_NAMESPACE, name = "UsernameToken") private UsernameToken usernameToken; }

    UsernameToken元素的POJO

    @XmlAccessorType(XmlAccessType.FIELD) @XmlRootElement(namespace = Security.SECURITY_NAMESPACE, name = "UsernameToken") @Getter @Setter public class UsernameToken { @XmlElement(namespace = Security.SECURITY_NAMESPACE, name = "Username") private String username; }
    最后,您可以使用以下内容来解析

    securityHeader

    public class SoapParser { public static Security parseSecurityElement(SoapHeaderElement soapHeaderElement) { Security securityElement = null; try { JAXBContext context = JAXBContext.newInstance(Security.class); Unmarshaller unmarshaller = context.createUnmarshaller(); securityElement = (Security) unmarshaller.unmarshal(soapHeaderElement.getSource()); } catch (JAXBException e) { e.printStackTrace(); } return securityElement; } }
    我希望这会有所帮助!
    © www.soinside.com 2019 - 2024. All rights reserved.