如何使用证书保护Spring soap服务

时间:2015-03-16 14:46:34

标签: java spring security soap certificate

我设法创建了一个肥皂服务器和客户端,需要用户名和密码才能调用函数。以下代码显示了我是如何完成此操作的

客户:

package hello;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextImpl;
import org.springframework.ws.client.support.interceptor.ClientInterceptor;
import org.springframework.ws.soap.security.xwss.XwsSecurityInterceptor;
import org.springframework.ws.soap.security.xwss.callback.SpringUsernamePasswordCallbackHandler;

@Configuration
public class SoftlayerConfiguration {

    @Bean
    public Jaxb2Marshaller marshaller() {
        Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
        marshaller.setContextPath("be.elision.soap.cloud");
        return marshaller;
    }

    @Bean
    public SoftlayerClient softlayerClient(Jaxb2Marshaller marshaller) {
        SoftlayerClient client = new SoftlayerClient();
        client.setDefaultUri("http://192.168.137.107:8080/ws");
        client.setMarshaller(marshaller);
        client.setUnmarshaller(marshaller);
        client.setInterceptors(new ClientInterceptor[]{securityInterceptor()});
        return client;
    }

    @Bean
    XwsSecurityInterceptor securityInterceptor() {
        XwsSecurityInterceptor securityInterceptor = new XwsSecurityInterceptor();
        securityInterceptor.setSecureRequest(true);
        securityInterceptor.setValidateRequest(true);
        securityInterceptor.setCallbackHandler(callbackHandler());
        securityInterceptor.setPolicyConfiguration(new ClassPathResource("securityPolicy.xml"));
        return securityInterceptor;
    }

    @Bean
    SpringUsernamePasswordCallbackHandler callbackHandler() {
        SecurityContextHolder.setContext(new SecurityContextImpl());
        SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken("user", "password"));
        return new SpringUsernamePasswordCallbackHandler();
    }

}

服务器

package be.elision.main;

import java.util.Collections;
import java.util.List;

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.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 {
    @Bean
    public ServletRegistrationBean messageDispatcherServlet(
            ApplicationContext applicationContext) {
        MessageDispatcherServlet servlet = new MessageDispatcherServlet();
        servlet.setApplicationContext(applicationContext);
        servlet.setTransformWsdlLocations(true);
        return new ServletRegistrationBean(servlet, "/ws/*");
    }

    @Bean(name = "devices")
    public DefaultWsdl11Definition defaultWsdl11Definition(
            XsdSchema devicesSchema) {
        DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
        wsdl11Definition.setPortTypeName("DevicesPort");
        wsdl11Definition.setLocationUri("/ws");
        wsdl11Definition.setTargetNamespace("http://elision.be/soap/cloud");
        wsdl11Definition.setSchema(devicesSchema);
        return wsdl11Definition;
    }

    // toevoegen van xsd aan bean
    @Bean
    public XsdSchema devicesSchema() {
        return new SimpleXsdSchema(new ClassPathResource("devices.xsd"));
    }

    @Bean
    XwsSecurityInterceptor securityInterceptor() {
        XwsSecurityInterceptor securityInterceptor = new XwsSecurityInterceptor();
        securityInterceptor.setCallbackHandler(callbackHandler());
        securityInterceptor.setPolicyConfiguration(new ClassPathResource(
                "securityPolicy.xml"));
        return securityInterceptor;
    }

    @Bean
    SimplePasswordValidationCallbackHandler callbackHandler() {
        SimplePasswordValidationCallbackHandler callbackHandler = new SimplePasswordValidationCallbackHandler();
        callbackHandler.setUsersMap(Collections
                .singletonMap("user", "password"));
        return callbackHandler;
    }

    @Bean
    PayloadLoggingInterceptor payloadLoggingInterceptor() {
        return new PayloadLoggingInterceptor();
    }

    @Bean
    PayloadValidatingInterceptor payloadValidatingInterceptor() {
        final PayloadValidatingInterceptor payloadValidatingInterceptor = new PayloadValidatingInterceptor();
        payloadValidatingInterceptor.setSchema(new ClassPathResource(
                "devices.xsd"));
        return payloadValidatingInterceptor;
    }

    @Override
    public void addInterceptors(List<EndpointInterceptor> interceptors) {
        interceptors.add(payloadLoggingInterceptor());
        interceptors.add(payloadValidatingInterceptor());
        interceptors.add(securityInterceptor());
    }

}

安全政策:

<xwss:SecurityConfiguration xmlns:xwss="http://java.sun.com/xml/ns/xwss/config">
    <xwss:UsernameToken digestPassword="false" useNonce="false" />
</xwss:SecurityConfiguration>

但现在我想用证书替换此用户名和密码身份验证。我不想在xml中这样做,而是在我现有的代码中实现它,如上所示。

1 个答案:

答案 0 :(得分:1)

我们几个月前最终想到了这一点,我记得我们的配置看起来像这样。

将此添加到您的web.xml

<servlet>
    <servlet-name>mvc-dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>mvc-dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

这需要出现在你的mvc-dispatcher-servlet.xml

    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans     
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
        http://www.springframework.org/schema/web-services
        http://www.springframework.org/schema/web-services/web-services-2.0.xsd">

    <context:component-scan base-package="com.yourpackage" />
    <bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory" />
    <bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
        <constructor-arg ref="messageFactory" />
        <property name="defaultUri"
            value="${backend.ip}devices" />
        <property name="interceptors">

            <list>
                <ref local="xwsSecurityInterceptor" />
            </list>
        </property>

    </bean>

    <bean id="xwsSecurityInterceptor"
        class="org.springframework.ws.soap.security.xwss.XwsSecurityInterceptor">
        <property name="policyConfiguration" value="/WEB-INF/securityPolicy.xml" />
        <property name="callbackHandlers">
            <list>
                <ref bean="keyStoreHandler" />
            </list>
        </property>
    </bean>

    <bean id="keyStore"
        class="org.springframework.ws.soap.security.support.KeyStoreFactoryBean">
        <property name="password" value="yourpassword" />
        <property name="location" value="/WEB-INF/yourkeystore.jks" />
    </bean>

    <bean id="keyStoreHandler"
        class="org.springframework.ws.soap.security.xwss.callback.KeyStoreCallbackHandler">
        <property name="keyStore" ref="keyStore" />
        <property name="privateKeyPassword" value="yourpassword" />
        <property name="defaultAlias" value="client" />
    </bean>

    <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix">
            <value>/WEB-INF/pages/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
    </bean>

    <!-- LOAD PROPERTIES -->
    <context:property-placeholder
        location="WEB-INF/config.properties"
        ignore-unresolvable="true" />

    <mvc:resources mapping="/resources/**" location="/resources/" />
    <mvc:annotation-driven />

</beans>

jks文件是一个包含证书的java密钥库文件。

SecurityPolicy.xml

    <xwss:SecurityConfiguration dumpMessages="true"     xmlns:xwss="http://java.sun.com/xml/ns/xwss/config">
   <xwss:Sign includeTimestamp="true">
         <xwss:X509Token certificateAlias="yourcertificatealias" /> 
    </xwss:Sign> 
</xwss:SecurityConfiguration>

这一切都是使用oracle的xws-security库完成的,你需要以下依赖项。

<dependency>
        <groupId>com.sun.xml.wss</groupId>
        <artifactId>xws-security</artifactId>
        <version>3.0</version>
        <exclusions>
            <exclusion>
                <groupId>javax.xml.crypto</groupId>
                <artifactId>xmldsig</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

在我们在这本很棒的书中找到关于证书身份验证的一些很好的解释后,我们完成了这项工作!

&#39; Spring Web Services 2 Cookbook,作者:Hamidreza Sattari&#39;

如果您对此实施有任何疑问,请随便提出! :d