webservice之自定義請求頭實現
阿新 • • 發佈:2019-01-23
需求:目前遇到一個呼叫webservice服務端的程式,需要開發客戶端呼叫程式,但是涉及到自定義請求頭,這個有一點麻煩
目前基於http+json的restful大行其道,所以本篇不介紹webservice服務開發過程,詳情可自行百度,基於cxf 可開發webservice和restful服務
好的,言歸正傳,本篇文章將會介紹webservice客戶端呼叫新增自定義請求頭的兩種方式,一種是jdk,一種藉助於cxf框架
自定義請求頭格式:
<auth>
<token></token>
<user></user>
<password ></password>
</auth>
服務端實現:
自定義頭部,需要自定義解析,本例服務端採用的是cxf,所以採用的是
攔截器AbstractPhaseInterceptor,攔截請求,解析頭部
public class AuthHeaderInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
private Logger log = Logger.getLogger(AuthHeaderInterceptor.class);
public AuthHeaderInterceptor() {
super(Phase.PRE_INVOKE);
}
@Override
public void handleMessage(SoapMessage msg) throws Fault {
try {
Header authHeader =null;
//獲取驗證頭
List<Header> headers = msg.getHeaders();
for(Header h:headers){
if(h.getName().toString().contains("auth")){
authHeader=h;
break ;
}
}
Element auth = (Element) authHeader.getObject();
NodeList childNodes = auth.getChildNodes();
String token,user,password;
for(int i=0,len=childNodes.getLength();i<len;i++){
Node item = childNodes.item(i);
if(item.getNodeName().contains("token")){
token=item.getTextContent();
// do check token
}
if(item.getNodeName().contains("user")){
user=item.getTextContent();
// do check user
}
if(item.getNodeName().contains("password")){
password=item.getTextContent();
// do check password
}
}
} catch (Exception e) {
e.printStackTrace();
log.error("許可權驗證異常");
throw new Fault(new Exception("請求頭auth不合法"));
}
}
}
客戶端實現
cxf 框架實現:
實現手段,攔截每次請求,新增自定義認證頭部;
繼承 AbstractSoapInterceptor
import java.util.List;
import javax.xml.namespace.QName;
import org.apache.cxf.binding.soap.SoapHeader;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor;
import org.apache.cxf.headers.Header;
import org.apache.cxf.helpers.DOMUtils;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.Phase;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
public class AuthHeaderInterceptor extends AbstractSoapInterceptor {
private String token;
private String user;
private String password;
public AuthHeaderInterceptor(String p, String token, String user, String password) {
super(p);
this.token = token;
this.user = user;
this.password = password;
}
public AuthHeaderInterceptor() {
super(Phase.WRITE);
}
public void handleMessage(SoapMessage message) throws Fault {
// SoapHeader部分待新增的節點
QName qName = new QName("auth");
Document doc = DOMUtils.createDocument();
// 驗證token
Element tokenEl = doc.createElement("token");
tokenEl.setTextContent(token);
Element pwdEl = doc.createElement("password");
pwdEl.setTextContent(password);
Element userEl = doc.createElement("user");
userEl.setTextContent(user);
Element root = doc.createElement("auth");
root.appendChild(tokenEl);
root.appendChild(userEl);
root.appendChild(pwdEl);
// 建立SoapHeader內容
SoapHeader header = new SoapHeader(qName, root);
// 新增SoapHeader內容
List<Header> headers = message.getHeaders();
headers.add(header);
}
}
客戶端呼叫,新增到outInterceptors
Client client= ClientProxy.getClient(service);
AuthHeaderInterceptor authHeaderInterceptor = new AuthHeaderInterceptor("token","user","password");
services.xxx(呼叫)
jdk 實現:
和cxf 原理差不多,都是在請求之前新增頭部,不過實現的是HandlerResolver 介面
//首先實現:新增頭部邏輯
public class RequesterCredentials implements SOAPHandler<SOAPMessageContext> {
private String token;
private String user;
private String password;
public RequesterCredentials(String token, String user, String password) {
super();
this.token = token;
this.user = user;
this.password = password;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public Set<QName> getHeaders() {
return null;
}
@Override
public void close(MessageContext context) {
}
@Override
public boolean handleFault(SOAPMessageContext context) {
// TODO return true
return true;
}
@Override
public boolean handleMessage(SOAPMessageContext context) {
addRequesterCredentials(context);
return true;
}
private void addRequesterCredentials(SOAPMessageContext context) {
try {
Boolean outboundProperty = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (outboundProperty.booleanValue()) {
SOAPMessage message = context.getMessage();
SOAPHeader header = message.getSOAPHeader();
if (header == null) {
message.getSOAPPart().getEnvelope().addHeader();
header = message.getSOAPHeader();
}
SOAPElement authenticationToken = header.addChildElement("auth", "", "");
authenticationToken.addChildElement("user").addTextNode(user);
authenticationToken.addChildElement("password").addTextNode(password);
authenticationToken.addChildElement("token").addTextNode(token);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public RequesterCredentials() {
}
}
//實現 HandlerResolver 介面
public class HeaderHandlerResolver implements HandlerResolver {
private RequesterCredentials requesterCredentials;
public HeaderHandlerResolver(RequesterCredentials requesterCredentials){
this.requesterCredentials=requesterCredentials;
}
@Override
public List getHandlerChain(PortInfo portInfo) {
return Arrays.asList(requesterCredentials);
}
}
最終效果: