【发布时间】:2015-03-16 14:46:33
【问题描述】:
我设法创建了一个需要用户名和密码才能调用函数的soap 服务器和客户端。以下代码显示了我是如何做到这一点的
客户:
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 中执行此操作,而是在我现有的代码中实现此操作,如上所示。
【问题讨论】:
-
你有没有想过这个问题?我必须编写一个 WSDL 客户端,它使用证书向服务器验证自己。存在大量 WSDL 部分的示例,证书部分没有那么多......
-
@JimArcher 一位团队成员为您发布了关于这个问题的答案!
标签: java spring security soap certificate