主要分为客户端和服务端
服务端
- pom配置
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>webservice-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>webservice-service</name>
<description>webservice-client</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- HTTP -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.4</version>
</dependency>
<!-- Fast Json -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.1.41</version>
</dependency>
<!-- CXF webservice -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-spring-boot-starter-jaxws</artifactId>
<version>3.3.3</version>
<exclusions>
<exclusion>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
- Config配置
@Configuration
public class CxfConfig {
@Autowired
private Bus bus;
@Autowired
private ServiceMaster serviceMaster;
//------------------------------------------ 默认是services ------------------------------------------
@Bean
public ServletRegistrationBean cxfServlet(){
return new ServletRegistrationBean( new CXFServlet(), "/services/*");
}
@Bean
public Endpoint endpoint(){
EndpointImpl endpoint = new EndpointImpl(bus, serviceMaster);
endpoint.publish("/ServiceMaster");
endpoint.getInInterceptors().add(new ClientLoginInterceptor());
endpoint.getInInterceptors().add(new AuthInterceptor());
return endpoint;
}
}
3.WebService拦截器验证
package com.example.webserviceclient.intercptor;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.binding.soap.saaj.SAAJInInterceptor;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.NodeList;
import javax.xml.soap.Name;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
/**
* 定义拦截器用户用户验证
*/
public class AuthInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
private static final Logger logger = LoggerFactory.getLogger(AuthInterceptor.class);
private SAAJInInterceptor saa = new SAAJInInterceptor();
private static final String USER_NAME = "guanguan";
private static final String USER_PASSWORD = "sailing2018!";
public AuthInterceptor() {
super(Phase.PRE_PROTOCOL);
getAfter().add(SAAJInInterceptor.class.getName());
}
@Override
public void handleMessage(SoapMessage message) throws Fault {
System.out.println("来了哟!"+message);
SOAPMessage mess = message.getContent(SOAPMessage.class);
if(mess==null){
saa.handleMessage(message);
mess=message.getContent(SOAPMessage.class);
}
SOAPHeader header =null;
try {
header = mess.getSOAPHeader();
} catch (SOAPException e) {
logger.error("getSOAPheader error:{}",e.getMessage(),e);
e.printStackTrace();
}
if(header==null){
throw new Fault(new IllegalAccessException("找不到Header,无法验证用户信息"));
}
NodeList username = header.getElementsByTagName("username");
NodeList password = header.getElementsByTagName("password");
if(username.getLength()<1){
throw new Fault(new IllegalAccessException("找不到Header,无法验证用户信息"));
}
if(password.getLength()<1){
throw new Fault(new IllegalAccessException("找不到Header,无法验证用户信息"));
}
String userName = username.item(0).getTextContent().trim();
String passWord = password.item(0).getTextContent().trim();
if(USER_NAME.equals(userName)&&USER_PASSWORD.equals(passWord)){
System.out.println("admin auth success");
logger.info("admin auth success");
}else {
SOAPException soapException = new SOAPException("认证错误");
logger.info("admin auth failed");
throw new Fault(soapException);
}
}
}
4.客户端用户密码登录验证
package com.example.webserviceclient.intercptor;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.headers.Header;
import org.apache.cxf.helpers.DOMUtils;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.xml.namespace.QName;
import java.util.List;
public class ClientLoginInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
private String username;
private String password;
public ClientLoginInterceptor() {
super(Phase.PREPARE_SEND);
}
public ClientLoginInterceptor(String username, String password) {
//super();
super(Phase.PREPARE_SEND);
this.username = username;
this.password = password;
}
@Override
public void handleMessage(SoapMessage soap) throws Fault {
List<Header> headers = soap.getHeaders();
Document doc = DOMUtils.createDocument();
Element auth = doc.createElement("authrity");
Element username = doc.createElement("username");
Element password = doc.createElement("password");
username.setTextContent(this.username);
password.setTextContent(this.password);
auth.appendChild(username);
auth.appendChild(password);
headers.add(0, new Header(new QName("timamaes"), auth));
}
}
5.service处理类
import com.example.webserviceclient.service.ServiceMaster;
import org.springframework.stereotype.Service;
import javax.jws.WebService;
@Service
@WebService(serviceName = "ServiceMaster", targetNamespace = "http://service.webserviceclient.example.com", endpointInterface = "com.example.webserviceclient.service.ServiceMaster")
public class ServiceMasterImpl implements ServiceMaster {
@Override
public String sendMessage(String username) {
System.out.println("---------------------"+username);
return "收到消息啦!" + username;
}
}
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
@WebService(name = "ServiceMaster", targetNamespace = "http://service.webserviceclient.example.com")//采用的是包的反向地址
public interface ServiceMaster {
@WebMethod
@WebResult(name = "String", targetNamespace = "http://service.webserviceclient.example.com")//采用的是包的反向地址
String sendMessage(@WebParam(name = "username") String username);
}
客户端
1.pom
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>webservice-client</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>webservice-client</name>
<description>webservice-client</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- HTTP -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.4</version>
</dependency>
<!-- Fast Json -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.1.41</version>
</dependency>
<!-- Web Service - cxf -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>3.3.3</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>3.3.3</version>
</dependency>
<!-- Junit -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
2.测试代码
import com.example.webserviceclient.interceptor.ClientLoginInterceptor;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
import org.junit.Test;
public class WebController {
@Test
public void TestClient(){
//---------------------------------------- 创建动态客户端 ----------------------------------------
JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
Client client = dcf.createClient("http://localhost:8080/services/ServiceMaster?wsdl");
//此地址为服务端请求地址,端口配置文件中没有指定,默认为8080
//------------------------------- 需要密码的情况需要加上用户名和密码 -----------------------------
client.getOutInterceptors().add(new ClientLoginInterceptor("guanguan", "sailing2018!"));
Object[] objects = new Object[0];
try {
// invoke("方法名",参数一,参数二,参数三....);
objects = client.invoke("sendMessage", "天黑请闭眼。。。");
System.out.println("返回数据:" + objects[0]);
} catch (java.lang.Exception e) {
e.printStackTrace();
}
}
}
认证通过时服务端后台打印
客服端打印
当认证不通过时
服务端
客户端