CXF Webservice非匿名訪問
關於這個非匿名訪問在網上找的不算多,自己也是多家融合,纔有點起色,在這裏記錄一下避免又忘了:
關於webservice咋寫的我就不多說了,網上一抓一大把,直接上有關cxf 非匿名訪問的代碼了哈
webservice公開的實現類
首頁是服務端的webservice上的註解哈,,注意這裏的serviceName (本人用的Spring+SpringMVC+Mybatis框架)
import javax.jws.WebService;
@Transactional
@Service
@WebService(endpointInterface = "com.sshome.ssmcxf.webservice.CompanyWebService", serviceName = "CompanyWebService")
public class CompanyWebServiceImpl implements CompanyWebService {
......
}
AuthInterceptor類 處理用戶名密碼
這裏是在客戶端直接自定義SOAP頭,然後到服務端的handler中拿到這個頭進行分析
package com.sshome.ssmcxf.webservice.impl;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
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.w3c.dom.Node;
public class AuthInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
private SAAJInInterceptor saa = new SAAJInInterceptor();
public AuthInterceptor() {
super(Phase.PRE_PROTOCOL);
getAfter().add(SAAJInInterceptor.class.getName());
}
public void handleMessage(SoapMessage message) throws Fault {
SOAPMessage mess = message.getContent(SOAPMessage.class);
if (mess == null) {
saa.handleMessage(message);
mess = message.getContent(SOAPMessage.class);
}
try {
SOAPHeader header = mess.getSOAPHeader();
if (header != null) {
Node userNameNode = header.getElementsByTagName("userName").item(0);
Node passwordNode = header.getElementsByTagName("password").item(0);
String userName = "", password = "";
if(userNameNode != null && passwordNode != null){
userName = userNameNode.getTextContent();
password = passwordNode.getTextContent();
if (userName != null && !"".equals(userName ) && password != null && !"".equals(password )) {
if(userName.equals("admin") && password.equals("123456")){
System.out.println("認證成功!!!");
}else{
SOAPException soapExc = new SOAPException("認證錯誤");
throw new Fault(soapExc);
}
}else{
SOAPException soapExc = new SOAPException("認證錯誤");
throw new Fault(soapExc);
}
}else{
SOAPException soapExc = new SOAPException("認證錯誤");
throw new Fault(soapExc);
}
} else {
SOAPException soapExc = new SOAPException("認證錯誤");
throw new Fault(soapExc);
}
} catch (SOAPException e) {
e.printStackTrace();
}
}
}
applicationContext-webservice.xml
webservice配置 重要等級五顆星哦,注意他們的對應關係,這個類肯定是要在web.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"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<!-- 這就是上面寫的類的地址啦 -->
<bean id="companyWebService" class="com.sshome.ssmcxf.webservice.impl.CompanyWebServiceImpl"/>
<bean id="inInterceptor" class="com.sshome.ssmcxf.webservice.impl.AuthInterceptor"/>
<!-- address的名稱就是訪問的WebService的name -->
<jaxws:server id="companyService" serviceClass="com.sshome.ssmcxf.webservice.CompanyWebService" address="/companyWebService">
<jaxws:serviceBean>
<!-- 要暴露的 bean 的引用 -->
<ref bean="companyWebService"/>
</jaxws:serviceBean>
<jaxws:inInterceptors>
<!-- 攔截處理用戶名密碼 -->
<ref bean="inInterceptor"/>
</jaxws:inInterceptors>
</jaxws:server>
</beans>
......
}
OK 服務端搞定啦,接下來就是偶們滴客戶端啦:
客戶端的AuthorityHeaderInterceptor類,配置服務器端Head信息的用戶密碼
package com.spring.test;
import java.util.List;
import javax.xml.namespace.QName;
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;
public class AuthorityHeaderInterceptor extends AbstractPhaseInterceptor<SoapMessage>{
private AuthorityParameter authorityParameter;
public AuthorityHeaderInterceptor(AuthorityParameter authorityParameter) {
super(Phase.PREPARE_SEND);
this.authorityParameter = authorityParameter;
}
public void handleMessage(SoapMessage msg) throws Fault {
List<Header> headers = msg.getHeaders();
//創建Document對象
Document doc = DOMUtils.createDocument();
//配置服務器端Head信息的用戶密碼
Element eleId= doc.createElement(this.authorityParameter.getUserNameKey());
eleId.setTextContent(this.authorityParameter.getUserNameValue());
Element elePass = doc.createElement(this.authorityParameter.getPasswordKey());
elePass.setTextContent(this.authorityParameter.getPasswordValue());
/**
* 也可以先創建一個父節點,則生成的XML文檔 ,我們這裏是直接使用用戶名和密碼
* <authHeader>
* <userId>admin</userId>
* <userPass>123456</userPass>
* </authHeader>
*/
headers.add(new Header(new QName(""), eleId));
headers.add(new Header(new QName(""), elePass));
}
}
參數類
package com.spring.test;
public class AuthorityParameter {
package com.spring.test;
public class AuthorityParameter {
/**
* 用戶名及密碼的字段、名稱
*/
private String userNameKey;
private String userNameValue;
private String passwordKey;
private String passwordValue;
public String getUserNameKey() {
return userNameKey;
}
public void setUserNameKey(String userNameKey) {
this.userNameKey = userNameKey;
}
public String getUserNameValue() {
return userNameValue;
}
public void setUserNameValue(String userNameValue) {
this.userNameValue = userNameValue;
}
public String getPasswordKey() {
return passwordKey;
}
public void setPasswordKey(String passwordKey) {
this.passwordKey = passwordKey;
}
public String getPasswordValue() {
return passwordValue;
}
public void setPasswordValue(String passwordValue) {
this.passwordValue = passwordValue;
}
public AuthorityParameter() {
super();
}
/**
* AuthorityParameter
* @param userNameKey 用戶名字段
* @param userNameValue 用戶名值
* @param passwordKey 密碼字段
* @param passwordValue 密碼值
*/
public AuthorityParameter(String userNameKey, String userNameValue, String passwordKey, String passwordValue) {
super();
this.userNameKey = userNameKey;
this.userNameValue = userNameValue;
this.passwordKey = passwordKey;
this.passwordValue = passwordValue;
}
}
然後肯定就是客戶端與服務端的連接與處理了
客戶端與服務端的連接方式有很多中,個人覺得這種連接方式比較便捷,至少對於我的項目來說是的,具體的各位自己參考
package com.spring.test;
import javax.xml.namespace.QName;
import net.sf.json.JSONObject;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
import org.apache.cxf.transport.http.HTTPConduit;
import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.alibaba.fastjson.JSONArray;
@Controller
@RequestMapping(value = "/demo", produces = { "text/json;charset=UTF-8" })
public class Demo {
@RequestMapping("/chart")
@ResponseBody
public String efficiency(){
//創建連接
JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
Client client = dcf.createClient("http://192.168.73.156:8080/Company_Service/companyWebService?wsdl");
AuthorityParameter param = new AuthorityParameter("userName", "admin", "password", "123456");
client.getOutInterceptors().add(new AuthorityHeaderInterceptor(param));
client.getOutInterceptors().add(new LoggingOutInterceptor());
HTTPClientPolicy policy = ((HTTPConduit) client.getConduit()).getClient();
policy.setConnectionTimeout(30000);
policy.setReceiveTimeout(180000);
try{
//連接方法的參數
String obj1 = "{\"TIME\":\"2018/04/20\",\"NUM\":\"8\"}";
//"http://webservice.ssmcxf.sshome.com/"爲webservice的命名空間,enterChart是我的方法名
Object[] objects = client.invoke(new QName("http://webservice.ssmcxf.sshome.com/", "enterChart"), new Object[]{obj1});
String result = objects[0].toString();// 返回值
System.out.println(result);
}
}