Spring boot Spring ws security for soap based web

2019-06-09 18:05发布

I have the following implementation in place for SOAP based web service and its security.

package com.hcentive.webservice.soap;

import org.apache.log4j.Logger;
import org.springframework.boot.context.embedded.ServletRegistrationBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.ws.config.annotation.EnableWs;
import org.springframework.ws.config.annotation.WsConfigurerAdapter;
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;

/**
 * @author Mebin.Jacob
 * Web service configuration class
 * @since 03-Sept-2014
 */
@EnableWs
@Configuration
@ImportResource({"classpath:/spring-ws-servlet.xml","classpath:/security.xml"})
public class WebServiceConfig extends WsConfigurerAdapter {

    Logger logger = Logger.getLogger(WebServiceConfig.class); 

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

    @Bean(name = "coa_application_service")
    public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema coa_applicationSchema) {
        DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
        wsdl11Definition.setPortTypeName("FormsPort");
        wsdl11Definition.setLocationUri("/ws");
        wsdl11Definition.setTargetNamespace("http://hcentive.com/service");
        wsdl11Definition.setSchema(coa_applicationSchema);
        return wsdl11Definition;
    }

    /*@Bean
    public EmbeddedServletContainerFactory servletContainer(){
        TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
        logger.info("Setting context path ");
        factory.setContextPath("/spring-ws-servlet.xml");
        return factory;
    }
*/
    @Bean
    public XsdSchema coa_applicationSchema() {
        return new SimpleXsdSchema(new ClassPathResource("coa_application_service.xsd"));
    }
}

//spring-ws-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    http://www.springframework.org/schema/security/spring-security-3.1.xsd">


    <bean id="wsSecurityInterceptor"
        class="org.springframework.ws.soap.security.xwss.XwsSecurityInterceptor">
        <property name="policyConfiguration" value="classpath:securityPolicy.xml" />
        <property name="callbackHandlers">
            <list>
                <ref bean="keyStoreHandler" />
                <ref bean="springCertificateHandler" />
            </list>
        </property>
    </bean>
    <bean id="keyStoreHandler"
        class="org.springframework.ws.soap.security.xwss.callback.KeyStoreCallbackHandler">
        <property name="keyStore" ref="keyStore" />
        <property name="privateKeyPassword" value="changeit" />
    </bean>

    <bean id="keyStore"
        class="org.springframework.ws.soap.security.support.KeyStoreFactoryBean">
        <property name="password" value="changeit" />
        <property name="location" value="classpath:/keystore.jks" />
    </bean>


    <bean id="springCertificateHandler"
        class="org.springframework.ws.soap.security.xwss.callback.SpringCertificateValidationCallbackHandler">
        <property name="authenticationManager">
            <bean class="com.hcentive.security.SimpleAuthenticationManager" />
        </property>
    </bean>

</beans>

//security.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/security
           http://www.springframework.org/schema/security/spring-security-3.2.xsd">

    <http>
        <!-- Every user request needs to be authenticated and authorized -->
        <intercept-url pattern="/**" access="ROLE_USER"/>

        <!-- x509 Pre authentication - pull username from the Common Name 
            field of the client certificate and extract the last 'word', in our client 
            cert example, 'John Smith jsmith', the username 'jsmith' -->
        <x509 subject-principal-regex="CN=.*?\s(\w+)," />

        <logout />
    </http>

      <authentication-manager>
        <authentication-provider>
            <user-service>
                <user name="Jacob" 
                    authorities="ROLE_USER, ROLE_ADMIN" />
            </user-service>
        </authentication-provider>
    </authentication-manager>


</beans:beans>

and this is what my logs shows :-

   Algorithm: [SHA256withRSA]
  Signature:
0000: 48 85 7A CA A7 1D DC 13   D1 0D 3D EB 10 20 A8 0E  H.z.......=.. ..
0010: 1D 2A 82 AF 0D 40 04 1A   4F 57 16 AF CF 2A 13 22  .*...@..OW...*."
0020: 79 A4 EB 81 29 13 56 94   78 AF EF D6 BE 3C B2 1B  y...).V.x....<..
0030: 7C B2 CC B6 69 00 56 41   58 A1 E5 03 5A 27 5B 97  ....i.VAX...Z'[.
0040: A5 49 8A 71 9C 78 13 0C   2D BC BD AE E5 26 52 9F  .I.q.x..-....&R.
0050: 8B EA 43 91 E0 DA 46 D2   15 C5 8B 23 E2 98 2E 9E  ..C...F....#....
0060: 67 80 07 C1 94 76 E8 89   8F E6 10 D2 C4 3A 41 80  g....v.......:A.
0070: A6 CA E9 59 4F A2 3C 6A   FB D9 71 C7 29 0A A1 83  ...YO.<j..q.)...
0080: D9 9E DE 09 F7 AC 18 EE   CE B2 A5 07 0C 0F C5 92  ................
0090: A8 82 3D 61 10 00 5A EC   90 E9 E7 94 72 CA 93 AA  ..=a..Z.....r...
00A0: 04 C3 83 61 4C 4D AD 08   D2 54 A8 96 58 5A 06 D3  ...aLM...T..XZ..
00B0: C2 0F 52 24 B1 7A EF 7C   52 27 92 88 34 EE 44 83  ..R$.z..R'..4.D.
00C0: E0 88 94 40 03 7A C3 7B   C8 D8 51 5A 0B 56 D3 22  ...@.z....QZ.V."
00D0: 36 11 04 B1 C0 8C F7 B3   B3 7C 4C F1 FF A4 50 41  6.........L...PA
00E0: 4A EE FC 2D 7C DE F2 54   3F 8A 38 B7 BF E3 6C 89  J..-...T?.8...l.
00F0: D1 3D 34 55 F5 F9 10 4B   77 A9 36 BF 23 5E 87 B4  .=4U...Kw.6.#^..

]
preAuthenticatedPrincipal = Jacob, trying to authenticate
Authentication attempt using org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider
PreAuthenticated authentication request: org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken@fbbdfcac: Principal: Jacob; Credentials: [PROTECTED]; Authenticated: false; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Not granted any authorities
Authentication success: org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken@fcc8a5: Principal: org.springframework.security.core.userdetails.User@44064bf: Username: Jacob; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN,ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_ADMIN, ROLE_USER
/ at position 5 of 10 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
/ at position 6 of 10 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
/ at position 7 of 10 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
SecurityContextHolder not populated with anonymous token, as it already contained: 'org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken@fcc8a5: Principal: org.springframework.security.core.userdetails.User@44064bf: Username: Jacob; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN,ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_ADMIN, ROLE_USER'
/ at position 8 of 10 in additional filter chain; firing Filter: 'SessionManagementFilter'
Delegating to org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy@11664436
HttpSession being created as SecurityContext is non-default
SecurityContext stored to HttpSession: 'org.springframework.security.core.context.SecurityContextImpl@fcc8a5: Authentication: org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken@fcc8a5: Principal: org.springframework.security.core.userdetails.User@44064bf: Username: Jacob; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN,ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_ADMIN, ROLE_USER'
/ at position 9 of 10 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
/ at position 10 of 10 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
Secure object: FilterInvocation: URL: /; Attributes: [ROLE_USER]
Previously Authenticated: org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken@fcc8a5: Principal: org.springframework.security.core.userdetails.User@44064bf: Username: Jacob; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN,ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_ADMIN, ROLE_USER
Voter: org.springframework.security.access.vote.RoleVoter@6290f34d, returned: 1
Authorization successful
RunAsManager did not change Authentication object
/ reached end of additional filter chain; proceeding with original chain
SecurityContext stored to HttpSession: 'org.springframework.security.core.context.SecurityContextImpl@fcc8a5: Authentication: org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken@fcc8a5: Principal: org.springframework.security.core.userdetails.User@44064bf: Username: Jacob; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN,ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_ADMIN, ROLE_USER'
Chain processed normally
SecurityContextHolder now cleared, as request processing completed
/error at position 1 of 10 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
Obtained a valid SecurityContext from SPRING_SECURITY_CONTEXT: 'org.springframework.security.core.context.SecurityContextImpl@fcc8a5: Authentication: org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken@fcc8a5: Principal: org.springframework.security.core.userdetails.User@44064bf: Username: Jacob; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN,ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_ADMIN, ROLE_USER'
/error at position 2 of 10 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
/error at position 3 of 10 in additional filter chain; firing Filter: 'LogoutFilter'
/error at position 4 of 10 in additional filter chain; firing Filter: 'X509AuthenticationFilter'
Checking secure context token: org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken@fcc8a5: Principal: org.springframework.security.core.userdetails.User@44064bf: Username: Jacob; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN,ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_ADMIN, ROLE_USER
/error at position 5 of 10 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
/error at position 6 of 10 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
/error at position 7 of 10 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
SecurityContextHolder not populated with anonymous token, as it already contained: 'org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken@fcc8a5: Principal: org.springframework.security.core.userdetails.User@44064bf: Username: Jacob; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN,ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_ADMIN, ROLE_USER'
/error at position 8 of 10 in additional filter chain; firing Filter: 'SessionManagementFilter'
/error at position 9 of 10 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
/error at position 10 of 10 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
/error reached end of additional filter chain; proceeding with original chain
Chain processed normally
SecurityContextHolder now cleared, as request processing completed

The authorization and access seems to be fine or perhaps I misunderstand something?? But the request does not seem to be going forward to my SOAP endpoint. I am a newbee with spring ws, spring boot. Have been stuck with this for a while. ....

Looks like after the loading of the filters the call to the messageDispatcherservlet is not made. Anyone any clue why that is not happening. I don't see any errors in my log!!!

Thanks, Mebin

1条回答
我欲成王,谁敢阻挡
2楼-- · 2019-06-09 18:36

I think you are mixing up two sorts of security here. In security.xml, you have enabled HTTP-based security with Spring Security, which operates on the HTTP transport layer only. In WebServiceConfig, you have enabled WS-Security with Spring Web Services, which operates on the SOAP message level. It's wise to pick one of the two, you probably want to have only WS-Security enabled.

Check here for a sample that uses WS-Security in a Spring Boot app. Specifically, see WebServiceServerConfig.

查看更多
登录 后发表回答