JAX-WS使用Handler实现简单的WebService权限验证
WebService如果涉及到安全保密或者使用权限的时候,WS-Security通常是最优选择。WS-Security (Web服务安全)
包含了关于如何在WebService消息上保证完整性和机密性的规约,如何将签名和加密头加入SOAP消息。
不过WS-Security也有一些性能上的损耗,在信息保密要求不是很高的情况下,可以通过在SOAPHeader中添加简单的校验信息实现。
具体思路是客户端调用需要认证的服务时,在SOAPHeader中添加授权信息(如用户名、密码或者序列号等)。
服务端收到请求,在SOAPHeader中校验授权信息,校验通过则执行请求,校验不通过则返回错误提示。
客户端发起请求在SOAPHeader中添加的授权数据格式如下
<auth xmlns="http://schemas.xmlsoap.org/soap/actor/next">
<username>admin</username>
<password>admin</password>
</auth>
服务端
服务端授权校验 Handler
import java.util.Iterator;
import java.util.Set; import javax.xml.namespace.QName;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPConstants;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFault;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext; import org.apache.cxf.interceptor.Fault;
import org.w3c.dom.NodeList; /**
*
* @author
*/
public class JaxServerAuthValidateHeader implements SOAPHandler<SOAPMessageContext> { @Override
public void close(MessageContext context) {
} @Override
public boolean handleFault(SOAPMessageContext context) {
return true;
} @Override
public boolean handleMessage(SOAPMessageContext context) { // 判断消息是输入还是输出
boolean isRequest = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
SOAPMessage soapMessage = context.getMessage(); if (!isRequest) { SOAPHeader soapHeader = null; try {
SOAPEnvelope soapEnv = soapMessage.getSOAPPart().getEnvelope();
soapHeader = soapEnv.getHeader();
} catch (SOAPException e) {
throw new Fault(new Exception("服务器异常!"));
} if (soapHeader == null) {
validateFail(soapMessage, "无 Soap Header 头信息!");
return false;
} // add an node named "auth"
QName qname = new QName(SOAPConstants.URI_SOAP_ACTOR_NEXT, "auth");
Iterator<?> iterator = soapHeader.getChildElements(qname);
SOAPElement auth = null;
if (iterator.hasNext()) {
// 获取auth
auth = (SOAPElement) iterator.next();
} // 如果授权信息元素不存在,提示错误
if (auth == null) {
validateFail(soapMessage, "无授权信息!");
return false;
} NodeList nameList = auth.getElementsByTagName("username");
NodeList pwdList = auth.getElementsByTagName("password");
if (nameList == null || nameList.getLength() <= 0 || pwdList == null || pwdList.getLength() <= 0) {
validateFail(soapMessage, "授权信息格式错误!");
return false;
} String username = nameList.item(0).getTextContent();
String password = pwdList.item(0).getTextContent();
if (!"admin".equals(username) || !"admin".equals(password)) {
validateFail(soapMessage, "授权信息格式错误!");
return false;
} } System.out.println(isRequest ? "服务端响应:" : "服务端接收:");
System.out.println("\r\n"); return true; } @Override
public Set<QName> getHeaders() {
return null;
} /**
* 授权校验失败,在SOAPBody中添加SOAPFault
*
* @param message
*/
private void validateFail(SOAPMessage soapMessage, String faultString) {
try { SOAPEnvelope envelop = soapMessage.getSOAPPart().getEnvelope(); envelop.getHeader().detachNode();
envelop.addHeader(); envelop.getBody().detachNode();
SOAPBody body = envelop.addBody(); SOAPFault fault = body.getFault(); if (fault == null) {
fault = body.addFault();
} fault.setFaultString(faultString); soapMessage.saveChanges(); } catch (SOAPException e) {
e.printStackTrace();
}
} }
服务端Handler配置文件handler-chain.xml
<?xml version="1.0" encoding="UTF-8"?>
<javaee:handler-chains xmlns:javaee="http://java.sun.com/xml/ns/javaee"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<javaee:handler-chain>
<javaee:handler>
<javaee:handler-class>com.server.handler.JaxServerAuthValidateHeader</javaee:handler-class>
</javaee:handler>
</javaee:handler-chain>
</javaee:handler-chains>
服务端的Service中添加Handler配置文件
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper; /**
* This class was generated by Apache CXF 3.2.1
* 2017-12-01T14:12:00.085+08:00
* Generated source version: 3.2.1
*
*/
@WebService(targetNamespace = "http://tempuri.org/", name = "AExampleDemoWebService")
@HandlerChain(file="handler-chain.xml")
public interface AExampleDemoWebService { @WebMethod
@WebResult(name = "single", targetNamespace = "")
public java.lang.String querySingle(
@WebParam(name = "single", targetNamespace = "http://tempuri.org/")
java.lang.String single
); }
服务端的Service 实现类
import java.util.ArrayList;
import java.util.List; import cn.evun.iwm.receive.soap.service.AExampleDemoWebService;
import cn.evun.iwm.receive.soap.struc.sample.InputParam;
import cn.evun.iwm.receive.soap.struc.sample.OutputParam; @javax.jws.WebService(serviceName = "aexampleDemoWebService", portName = "Sample",
targetNamespace = "http://tempuri.org/", endpointInterface = "cn.soap.service.AExampleDemoWebService")
public class AExampleDemoWebServiceImpl implements AExampleDemoWebService { @Override
public String querySingle(String input) {
return "success";
} }
客户端
客户端添加授权Handler
import java.io.IOException;
import java.util.Set; import javax.xml.namespace.QName;
import javax.xml.soap.SOAPConstants;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext; public class JaxWsClientHandler implements SOAPHandler<SOAPMessageContext> { @Override
public boolean handleMessage(SOAPMessageContext context) { // 判断消息是请求还是响应
Boolean isRequest = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
SOAPMessage soapMessage = context.getMessage(); if (isRequest) { try { SOAPHeader soapHeader = soapMessage.getSOAPHeader();
if (soapHeader == null) {
soapHeader = soapMessage.getSOAPPart().getEnvelope().addHeader();
} // add an node named "auth"
QName qname = new QName(SOAPConstants.URI_SOAP_ACTOR_NEXT, "auth");
SOAPElement auth = soapHeader.addChildElement(qname); SOAPElement name = auth.addChildElement("username");
name.addTextNode("admin"); SOAPElement password = auth.addChildElement("password");
password.addTextNode("admin"); soapMessage.saveChanges(); // tracking
soapMessage.writeTo(System.out); } catch (SOAPException e) {
System.err.println(e);
} catch (IOException e) {
System.err.println(e);
} } return true; } @Override
public boolean handleFault(SOAPMessageContext context) {
return false;
} @Override
public void close(MessageContext context) { } @Override
public Set<QName> getHeaders() {
return null;
} }
客户端Handler配置文件handler-chain.xml
<?xml version="1.0" encoding="UTF-8"?>
<javaee:handler-chains xmlns:javaee="http://java.sun.com/xml/ns/javaee"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<javaee:handler-chain>
<javaee:handler>
<javaee:handler-class>com.client.handler.JaxWsClientHandler</javaee:handler-class>
</javaee:handler>
</javaee:handler-chain>
</javaee:handler-chains>
客户端的Service中添加Handler配置文件
import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.ws.WebEndpoint;
import javax.xml.ws.WebServiceClient;
import javax.xml.ws.WebServiceFeature; import javax.xml.ws.Service; /**
* This class was generated by Apache CXF 3.2.1
* 2017-12-01T14:12:00.117+08:00
* Generated source version: 3.2.1
*
*/
@WebServiceClient(name = "aexampleDemoWebService",
wsdlLocation = "http://localhost:8090/service/Sample?wsdl",
targetNamespace = "http://tempuri.org/")
@HandlerChain(file="handler-chain.xml")
public class AexampleDemoWebServiceSoap extends Service { public final static URL WSDL_LOCATION; public final static QName SERVICE = new QName("http://tempuri.org/", "aexampleDemoWebService");
public final static QName Sample = new QName("http://tempuri.org/", "Sample");
static {
URL url = null;
try {
url = new URL("http://localhost:8090/service/Sample?wsdl");
} catch (MalformedURLException e) {
java.util.logging.Logger.getLogger(AexampleDemoWebServiceSoap.class.getName())
.log(java.util.logging.Level.INFO,
"Can not initialize the default wsdl from {0}", "http://localhost:8090/service/Sample?wsdl");
}
WSDL_LOCATION = url;
} public AexampleDemoWebServiceSoap(URL wsdlLocation) {
super(wsdlLocation, SERVICE);
} public AexampleDemoWebServiceSoap(URL wsdlLocation, QName serviceName) {
super(wsdlLocation, serviceName);
} public AexampleDemoWebServiceSoap() {
super(WSDL_LOCATION, SERVICE);
} public AexampleDemoWebServiceSoap(WebServiceFeature ... features) {
super(WSDL_LOCATION, SERVICE, features);
} public AexampleDemoWebServiceSoap(URL wsdlLocation, WebServiceFeature ... features) {
super(wsdlLocation, SERVICE, features);
} public AexampleDemoWebServiceSoap(URL wsdlLocation, QName serviceName, WebServiceFeature ... features) {
super(wsdlLocation, serviceName, features);
} /**
*
* @return
* returns AExampleDemoWebService
*/
@WebEndpoint(name = "Sample")
public AExampleDemoWebService getSample() {
return super.getPort(Sample, AExampleDemoWebService.class);
} /**
*
* @param features
* A list of {@link javax.xml.ws.WebServiceFeature} to configure on the proxy.
* Supported features not in the <code>features</code> parameter will have their default values.
* @return
* returns AExampleDemoWebService
*/
@WebEndpoint(name = "Sample")
public AExampleDemoWebService getSample(WebServiceFeature... features) {
return super.getPort(Sample, AExampleDemoWebService.class, features);
} }
客户端发起请求
QName SERVICE_NAME = new QName("http://tempuri.org/", "aexampleDemoWebService");
URL url = new URL("http://localhost:8090/service/Sample?wsdl");
AexampleDemoWebServiceSoap ss = new AexampleDemoWebServiceSoap(wsdlURL, SERVICE_NAME);
AExampleDemoWebService port = ss.getSample();
port.querySingle("1111");
@HandlerChain 注解 替代方式
客户端 通过 HandlerReolver 代替 @HandlerChain 注解 导入 Handler 配置文件
handler-chain配置文件对所有的请求都添加授权验证信息,有些时候不是所有的请求都需要添加授权验证,HandlerResolver提供了在编程时添加Handler的方法,可以用HandlerResolver给需要授权的接口添加Handler。
QName SERVICE_NAME = new QName("http://tempuri.org/", "aexampleDemoWebService");
URL url = new URL("http://localhost:8090/service/Sample?wsdl");
AexampleDemoWebServiceSoap ss = new AexampleDemoWebServiceSoap(wsdlURL, SERVICE_NAME);
//通过HandlerResolver添加Handler
ss.setHandlerResolver(new HandlerResolver(){
@Override
@SuppressWarnings("rawtypes")
public List<Handler> getHandlerChain(PortInfo portInfo) {
List<Handler> handlerChain = new ArrayList<Handler>();
handlerChain.add(new JaxWsClientHandler());
return handlerChain;
}
});
AExampleDemoWebService port = ss.getSample();
port.querySingle("2222");
服务端 @HandlerChain 注解替代
服务发布时服务端通过继承至 Endpoint 实现类 EndpointImpl 的 setHandlers 方法添加头部信息 代替 @HandlerChain 注解 导入 Handler 配置文件
import java.util.ArrayList;
import java.util.List; import javax.xml.ws.Endpoint;
import javax.xml.ws.handler.Handler; import org.apache.cxf.Bus;
import org.apache.cxf.bus.spring.SpringBus;
import org.apache.cxf.interceptor.Interceptor;
import org.apache.cxf.jaxws.EndpointImpl;
import org.apache.cxf.message.Message;
import org.apache.cxf.transport.servlet.CXFServlet;
import org.springframework.boot.context.embedded.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; @Configuration
public class CXFConfig { @Bean
public ServletRegistrationBean dispatcherServlet() {
return new ServletRegistrationBean(new CXFServlet(), "/service/*");
} @Bean(name = Bus.DEFAULT_BUS_ID)
public SpringBus springBus() {
return new SpringBus();
} @Bean
public AExampleDemoWebServiceImpl aExampleDemoWebServiceImpl() {
return new AExampleDemoWebServiceImpl();
} @Bean
public Endpoint endpointWebServiceSampleImpl() { EndpointImpl endpoint = new EndpointImpl(springBus(), aExampleDemoWebServiceImpl()); // SOAPHandler 方式
@SuppressWarnings("rawtypes")
List<Handler> handlers = new ArrayList<>();
handlers.add(new JaxServerAuthValidateHeader());
endpoint.setHandlers(handlers); endpoint.publish("/Sample"); return endpoint; } }
当使用替代方式添加头部信息的时候就不需要使用 @HandlerChain 注解
JAX-WS使用Handler实现简单的WebService权限验证的更多相关文章
- 一个简单的webservice的demo(下)winform异步调用webservice
绕了一大圈,又开始接触winform的项目来了,虽然很小吧.写一个winform的异步调用webservice的demo,还是简单的. 一个简单的Webservice的demo,简单模拟服务 一个简单 ...
- 一个简单的Webservice的demo,简单模拟服务
前段时间一直在学习WCF,匆匆忙忙的把<WCF全面解析>和<WCF服务编程>看了一遍,好多东西都不是很懂,又听了一下WCF分布式开发的网络教程,算是马马虎虎的明白点了.回顾了一 ...
- 一个简单的webservice调用
我们先创建一个简单空web应用程序 然后添加新建项目 //我们创建一个peson对象,产生数据标识返回 using System; using System.Collections.Generic; ...
- 利用Java编写简单的WebService实例
使用Axis编写WebService比較简单,就我的理解,WebService的实现代码和编写Java代码事实上没有什么差别,主要是将哪些Java类公布为WebService. 以下是一个从编写測试样 ...
- 利用Java编写简单的WebService实例-转载
使用Axis编写WebService比较简单,就我的理解,WebService的实现代码和编写Java代码其实没有什么区别,主要是将哪些Java类发布为WebService.下面是一个从编写测试例子到 ...
- 一个简单的Webservice的demo(中)_前端页面调用
首先新建项目,这里有两种调用方式,为了能方便理解,新建页面WebserviceTest如下图: 先引用写好的服务,这里用上次写好的服务.见上次写的一个简单的Webservice的demo,简单模拟服务 ...
- 一个简单的WebService实例
WebService在.NET平台下的作用是在不同应用程序间共享数据与数据交换. 要达到这样的目标,Web services要使用两种技术: XML(标准通用标记语言下的一个子集):XML是在web上 ...
- (转)Web Service入门简介(一个简单的WebService示例)
Web Service入门简介 一.Web Service简介 1.1.Web Service基本概念 Web Service也叫XML Web Service WebService是一种可以接收从I ...
- 利用VS2008发布一个简单的webservice
一个开发好的webservice,怎样发布出去,供其他电脑访问呢? 本文将介绍如何发布一个简单的webservice,其中的内容都是在网上查看别人文章,自己仿照着做了一遍,因此,难免会发生错误,如果发 ...
随机推荐
- Git 学习(二)版本库创建
Git 版本库创建 什么是版本库(repository)? 可理解为文件仓库.由Git管理每个文件的新增.修改及删除,但这个仓库可以追溯历史.可还原至任意历史节点. 版本库创建 创建一个版本库非常简单 ...
- uva 10994 - Simple Addition(规律)
题目链接:uva 10994 - Simple Addition 题目大意:给出l和r,求∑(l≤i≤r)F(i), F(i)函数题目中有. 解题思路:由两边向中间缩进,然后l和r之间的数可以按照1~ ...
- Python爬虫(3)豆瓣登录
前面(1)(2)的内容已经足够爬虫如链家网之类的不需要登录可以直接获取数据的网站. 而要爬取社交网站比较鲜明的特点就是需要登录,否则很多东西都无法获取.经过测试发现,微博,知乎都不是很好登录,知乎有时 ...
- 一次WEB前端优化尝试
今天对自己做的项目中的一个设计器界面加载速度上进行了优化,因为页面在加载的时候,感觉有点慢.首先,我用firefox的yslow和chrome的pagespeed进行了测试,效果如下,分数有点不同,但 ...
- C#的四个基本技巧
1.如果可能尽量使用接口来编程 .NET框架包括类和接口,在编写程序的时候,你可能知道正在用.NET的哪个类.然而,在这种情况下如果你用.NET支持的接口而不是它的类来编程时,代码会变得更加稳定.可用 ...
- mysql之子查询
所谓子查询,就是指在一个查询之中嵌套了其他的若干查询,通过子查询可以实现多表查询,该查询语句中可能包含IN,ANY,ALL和EXISTS等关键字,除此之外还可以包含比较运算符,子查询经常出现在WHER ...
- JAVA , TOMCAT , AXIS2 环境变量配置
想要成功配置Java的环境变量,那肯定就要安装JDK,才能开始配置的. 安装JDK 向导进行相关参数设置.如图: 正在安装程序的相关功能,如图: 选择安装的路径,可以自定义,也可以默认路径.如图: 成 ...
- Windows10+Ubuntu双系统安装[
数据备份先别着急,你备份了吗?如果你看到这里,说明你选择了风险最大的一条路,在游戏开始之前,一定要做好数据备份,数据备份,数据备份. 创建磁盘分区 按住Win + X,选择“磁盘管理”: 磁盘管理概览 ...
- 公司上线流程 pushonline_alpha
这是在公司将服务部署上线的一个记录,只是部署很小的python脚本,各公司不同,参考性不是很大 开始吧(版本管理是git) 1.整理好代码后:git add xxx.py git commit -m ...
- JS-为句柄添加监听函数
具体谈如何实现JS为句柄添加监听函数之前先看一段代码,算是抛出这个问题. <html> <head> <title>JS为句柄添加监听函数</title> ...