唠叨两句

讲真,SOAP跟现在流行的RESTful WebService比起来显得很难用。冗余的XML文本信息太多,可读性差,它的请求信息有时很难手动构造,不太好调试。不过说归说,对某些企业用户来说SOAP的使用率仍然是很高的。

需求背景

接手维护的一个项目,最近客户想开放项目中的功能给第三方调用,而且接入方指定必须是SOAP接口。这项目原来的代码我看着头疼,也不想再改了,除非推倒重写。客户的需求虽然不难但要的很急,为了尽快交付就使用SpringBoot快速搭一个微服务。

开始动手

.新建一个Spring Starter Project
.加入cxf的maven配置
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-spring-boot-starter-jaxws</artifactId>
<version>3.1.</version>
</dependency>

编写服务代码(示例代码)

@WebService(targetNamespace="http://demo.example.com/")
public interface IUserService { @WebMethod
User getUserById(@WebParam(name = "id") int id); @WebMethod
int addUser(@WebParam(name = "user") User user);
}
@InInterceptors(interceptors={"com.example.demo.auth.AuthInterceptor"})
@WebService(serviceName = "UserService", targetNamespace = "http://demo.example.com/", endpointInterface = "com.example.demo.soap.IUserService")
@Component
public class UserServiceImpl implements IUserService { private Logger logger = LoggerFactory.getLogger(UserServiceImpl.class); @Autowired
private IUserDAO userDAO; @Override
public User getUserById(int id) {
return userDAO.getUserById(id);
} @Override
public int addUser(User user) {
logger.info("save user [" + user.getId() + "]");
userDAO.addUser(user);
return 0;
}
}

鉴权拦截器

public class AuthInterceptor extends AbstractSoapInterceptor {

    private static final String BASIC_PREFIX = "Basic ";
private static final String USERNAME = "lichmama";
private static final String PASSWORD = "123456"; public AuthInterceptor() {
super(Phase.PRE_INVOKE);
} @Override
public void handleMessage(SoapMessage message) throws Fault {
HttpServletRequest request = (HttpServletRequest) message.get(AbstractHTTPDestination.HTTP_REQUEST);
String auth = request.getHeader("Authorization");
if (auth == null) {
SOAPException exception = new SOAPException("auth failed, header [Authorization] not exists");
throw new Fault(exception);
}
if (!auth.startsWith(BASIC_PREFIX)) {
SOAPException exception = new SOAPException("auth failed, header [Authorization] is illegal");
throw new Fault(exception);
}
String plaintext = new String(Base64.getDecoder().decode(auth.substring(BASIC_PREFIX.length())));
if (StringUtils.isEmpty(plaintext) || !plaintext.contains(":")) {
SOAPException exception = new SOAPException("auth failed, header [Authorization] is illegal");
throw new Fault(exception);
}
String[] userAndPass = plaintext.split(":");
String username = userAndPass[0];
String password = userAndPass[1];
if (!USERNAME.equals(username) || !PASSWORD.equals(password)) {
SOAPException exception = new SOAPException("auth failed, username or password is incorrect");
throw new Fault(exception);
}
}
}

编写配置类

@Configuration
public class SoapConfig { @Autowired
private IUserService userService; @Autowired
@Qualifier(Bus.DEFAULT_BUS_ID)
private SpringBus bus; @Bean
public Endpoint endpoint() {
EndpointImpl endpoint = new EndpointImpl(bus, userService);
endpoint.publish("/userService");
return endpoint;
}
}

修改CXF默认发布路径(application.properties)

server.port=8000
cxf.path=/soap

启动项目后访问http://localhost:8000/soap/userService?wsdl

使用SoapUI测试一下,看上去没什么问题

客户端增加对Basic Auth的支持:

/*
使用Eclipse自动生成Web Service Client,在SoapBingdingStub的createCall()方法中加入一下代码:
*/ // basic auth
_call.setProperty("javax.xml.rpc.security.auth.username", "lichmama");
_call.setProperty("javax.xml.rpc.security.auth.password", "123456");

然后正常调用即可,这里提供一下自己写的SoapClient:

public class GeneralSoapClient {

    private String WSDL;

    private String namespaceURI;

    private String localPart;

    public GeneralSoapClient() {

    }

    public GeneralSoapClient(String WSDL, String namespaceURI, String localPart) {
this.WSDL = WSDL;
this.namespaceURI = namespaceURI;
this.localPart = localPart;
} public String getWSDL() {
return WSDL;
} public void setWSDL(String WSDL) {
this.WSDL = WSDL;
} public String getNamespaceURI() {
return namespaceURI;
} public void setNamespaceURI(String namespaceURI) {
this.namespaceURI = namespaceURI;
} public String getLocalPart() {
return localPart;
} public void setLocalPart(String localPart) {
this.localPart = localPart;
} private boolean requireAuth = false; private String username; private String password; public boolean isRequireAuth() {
return requireAuth;
} public void setRequireAuth(boolean requireAuth) {
this.requireAuth = requireAuth;
} public String getUsername() {
return username;
} public void setUsername(String username) {
this.username = username;
} public String getPassword() {
return password;
} public void setPassword(String password) {
this.password = password;
} /**
* 创建Soap Service实例
* @param serviceInterface
* @return
* @throws Exception
*/
public <T> T create(Class<T> serviceInterface) throws Exception {
URL url = new URL(WSDL);
QName qname = new QName(namespaceURI, localPart);
Service service = Service.create(url, qname);
T port = service.getPort(serviceInterface);
if (requireAuth) {
BindingProvider prov = (BindingProvider) port;
prov.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, username);
prov.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, password);
}
return port;
}
}
public class TestSoap {

    public static void main(String[] args) throws Exception {
String wsdl = "http://localhost:8080/soap/userService?wsdl";
String namespaceURI = "http://demo.example.com/";
String localPart = "UserService";
GeneralSoapClient soapClient = new GeneralSoapClient(wsdl, namespaceURI, localPart);
soapClient.setRequireAuth(true);
soapClient.setUsername("lichmama");
soapClient.setPassword("123456");
IUserService service = soapClient.create(IUserService.class);
User user = service.getUserById(101);
}
}

最后交代一下开发环境

STS 3.7.3 + SpringBoot 2.0.1 + JDK1.8

收工下班了。

SpringBoot + CXF快速实现SOAP WebService(支持Basic Auth)的更多相关文章

  1. 时隔五年,Scrapyd 终于原生支持 basic auth

    Issue in 2014 scrapy/scrapyd/issues/43 Pull request in 2019 scrapy/scrapyd/pull/326 试用 1. 安装: pip in ...

  2. Spring Boot SOAP Webservice例子

    前言 本文将学习如何利用Spring boot快速创建SOAP webservice服务: 虽然目前REST和微服务越来越流行,但是SOAP在某些情况下,仍然有它的用武之地: 在本篇 spring b ...

  3. 使用crypt配置Basic Auth登录认证

    简介 Basic Auth用于服务端简单的登录认证,通常使用服务器Nginx.Apache本身即可完成.比如我们要限定某个域名或者页面必须输入用户名.密码才能登录,但又不想使用后端开发语言,此时Bas ...

  4. Etcd安全配置之Basic Auth认证

    <中小团队落地配置中心详解>文章中我们介绍了如何基于Etcd+Confd构建配置中心,最后提到Etcd的安全问题时说了可以使用账号密码认证以达到安全访问的目的,究竟该如何开启认证以及怎么设 ...

  5. 使用CXF实现基于Soap协议的WebService

    本文介绍使用CXF实现基于Soap协议的WebService(CXF的版本是3.0.0) 一. 前言 Java有三种WebService规范:Jax-WS,Jax-RS,Jaxm 1. Jax-WS( ...

  6. CXF整合Spring发布WebService实例

    一.说明: 上一篇简单介绍了CXF以及如何使用CXF来发布一个简单的WebService服务,并且介绍了客户端的调用. 这一篇介绍如何使用CXF与spring在Web项目中来发布WebService服 ...

  7. 通过CXF,开发soap协议接口

    1. 引入cxf的jar包 pom文件里面直接增加依赖 < dependency> <groupId > junit</ groupId> <artifact ...

  8. Apache CXF使用Jetty发布WebService

    一.概述 Apache CXF提供了用于方便地构建和开发WebService的可靠基础架构.它允许创建高性能和可扩展的服务,可以部署在Tomcat和基于Spring的轻量级容器中,也可以部署在更高级的 ...

  9. 使用CXF框架,发布webservice服务,并使用客户端远程访问webservice

    使用CXF框架,发布webservice服务,并使用客户端远程访问webservice  1. CXF介绍 :soa的框架    * cxf 是 Celtrix (ESB框架)和 XFire(webs ...

随机推荐

  1. Angular复习笔记7-路由(上)

    Angular复习笔记7-路由(上) 关于Angular路由的部分将分为上下两篇来介绍.这是第一篇. 概述 路由所要解决的核心问题是通过建立URL和页面的对应关系,使得不同的页面可以用不同的URL来表 ...

  2. ASP.NET SignalR 系列(七)之服务端触发推送

    前面几章讲的都是从客户端触发信息推送的,但在实际项目中,很多信息可能是由系统服务端推送的,下面2图分别展示两种通道 客户端触发推送 服务端推送 下面我们就重点介绍下服务端如何调用集线器的对象进行推送 ...

  3. 关于BASE 24 ,BASE 64原理以及实现程序

    关于BASE 24 ,BASE 64原理以及实现程序 来源 https://wangye.org/blog/archives/5/ 可能很多人听说过Base64编码,很少有人听说过Base24编码,B ...

  4. Java自学-操作符 逻辑操作符

    Java的逻辑运算符 逻辑运算符 示例 1 : 长路与 和 短路与 无论长路与还是短路与 两边的运算单元都是布尔值 都为真时,才为真 任意为假,就为假 区别: 长路与 两侧,都会被运算 短路与 只要第 ...

  5. 记录下Hbuilder 打包IOS发布时 总是提示错误:ios prifile文件与私钥证书匹配 的问题

    最近两天,新的APP准备要上线,然后打包正式发布版 时,总是提示不匹配 证书照hbuilder里面的文档 一样也不行,然后百度了N种方法,都是不行,而且也比较少搜索到相关问题. 后来都是谷歌了下,找到 ...

  6. CDA数据分析实务【第一章:营销决策分析概述】

    一.营销概述 营销是关于企业如何发现.创造和交付价值以满足一定目标市场的需求,同时获取利润的学科.营销学用来辨识未被满足的需求,定义,度量目标市场的规模和利润潜力,找到最合适企业进入的细分市场和适合该 ...

  7. BLAS快速入门

    一.简介 BLAS[Basic Linear Algebra Subprograms,基础线性代数程序集]是一个应用程序接口[API]标准,用于规范发布基础基础线性代数操作的数值库[常用于向量或矩阵计 ...

  8. Linux运维技术之NFS网络文件系统

    NFS:网络文件系统,只能工作在Unix/linux之间,不能与windows之间交互. NFS文件系系统只能基于ip来认证! RPC:远程过程调用,简化分布式应用程序的开发, 对Linux系统而言, ...

  9. 漏洞利用 Exploit---利用默认口令、IP假冒、应用漏洞

    漏洞利用 编辑 讨论 本词条由“科普中国”科学百科词条编写与应用工作项目 审核 . 漏洞利用(英语:Exploit,本意为“利用”)是计算机安全术语,指的是利用程序中的某些漏洞,来得到计算机的控制权( ...

  10. Linux查看打日志文件

    1.如果文件比较小的话,使用vim直接查看,如果文件比较大的话,使用vim会直接卡主 2.如果想要查看正在滚动的日志文件.这个命令可以查看大文件. tail -f file Ctrl+c 终止tail ...