




已阅读5页,还剩30页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
基于XFire实施WS-Security概述Web Service是安全的吗?鉴于安全性涉及诸多方面(例如身份验证和授权、数据隐私和完整性等),而 SOAP 规范中根本没有提及安全性这一事实,所以我们不难理解人们为什么认为答案是否定的。很少有不需要某种形式的安全性保证的企业级系统。在 Web Service中,处理Web Service安全的过程比处理其他领域应用的安全问题更为复杂,因为Web Service具有分布式、无状态的特性。WS-Security是解决Web Service安全问题的规范,大多数商业的Java EE应用服务器都实现了WS-Security规范,Apache WSS4J是WS-Security的开源实现,WSS4J通过SOAP中WS-Security相关的信息对SOAP报文进行验证和签名,XFire通过WSS4J对WS-Security提供了支持。你可以从/wss4j了解更多关于WSS4J的信息。认识WS-Security 2002 年 4 月,IBM、Microsoft 和 VeriSign 在他们的 Web 站点上提议建立 Web Services Security (WS-Security)规范。此规范包括安全凭证、XML签名和XML加密的安全性问题。此规范还定义了用户名凭证和已编码的二进制安全性凭证的格式。2002 年 6 月,OASIS 从 IBM、Microsoft 和 Verisign 接收到了提议的WS-Security安全性规范。不久之后就在 OASIS 成立了“Web Service 安全性技术委员会”(WSS TC)。2006年2月15日,OASIS通过了WS-Security 1.1安全规范,1.1规范突出了对安全权标支持、消息附件和权限管理的增强。1.1规范包括WS-Security核心规范及用户名权标规范1.1、X.509权标规范1.1、Kerberos权标规范1.1、SAML权标规范1.1、权限表达(REL)权标规范1.1、带附件的SOAP(SWA)规范1.1和模式1.1。也许读者会提出这样的问题:SSL也具有完整性和机密性,为什么还需要另外一个WS-Security规范呢?之所以要制定WS-Security规范,是SSL存在以下的问题: 端对端的通信,脱离传输层就无法保证安全性; 消息必须全部加密/或者全部签名,而不能针对消息的某部分,没有考虑XML处理。 SSL对应OSI的传输层,前面我们提到过Web Service是和传输层无关的,将安全问题依附在SSL上就违反了Web Serivce与传输层无关的原则。而WS-Security对应于OSI的应用层,建立消息层SOAP之上。针对不同领域的细分问题,OASIS 在WS-Security的基础上又制定了几十个规范,其中包括WS-SecureConversation、WS-Federation、 WS-Authorisation、WS-Policy、WS-Trust、WS-Privacy等,形成了一个庞大Web Service安全性协议家族。图1 WS-Security所在位置有了WS-Security规范,用户就拥有在Web Service应用中实施完整性、机密性和身份验证等安全需求的规范方法。XFire应用WS-Security的总体方案XFire通过Apache的WSS4J对WS-Security提供支持,XFire完整发布包中包含了WSS4J的类包。我们知道XFire在发送和接收SOAP报文前拥有多个阶段,每个阶段都可以注册Handler,对SOAP报文进行前置和后置处理的加工操作。XFire即通过Handler实施WSS4J,当发送SOAP报文时,通过注册一系列OutHandler,对SOAP报文进行加密、签名、添加用户身份信息等后置处理操作。而在接收SOAP报文时,则通过注册一系列的InHandler对SOAP进行解密、验证签名,用户身份认证等前置操作。图2 XFire应用WS-Security的方案请求和响应的SOAP在发送之前可以通过注册的OutHanlder进行加工处理,让SOAP转换为WS-Security的保护格式。而服务端和客户端的接收SOAP 报文之前,可以通过注册的InHandler,将WS-Security格式的SOAP转换正常的SOAP进行处理。由于XFire在SOAP收发过程中定义了多个不同的生命阶段,所以可以在发送前和接收前完成SOAP报文安全处理的工作,这些操作完全独立于业务处理逻辑,实施WS-Security对于Web Service的业务操作是透明的。使用WS-Security在前面内容中,我们通过各种方式将BbtForum中的方法以BbtForumSerivice窄接口开放为Web Service服务,但个Web Service是没有任何安全性可言的,任何拿到WSDL的人都可以轻松地构造客户端程序访问我们的Web Service服务。在这节里,我们将解决这个问题,对BbtForumSerivice添加不同的安全功能。准备工作在使用XFire的WS-Security之前,必须做一些准备性的工作:包括搭建安全环境,创建密钥对和证书等内容。安装Java策略文件策略文件被JDK使用,用以控制加密的强度和算法。确认已经安装对应JDK 版本的Unlimited Strength Jurisdiction策略文件,这是一个无限制的安全控制文件。你可以从/j2se/1.5.0/download.jsp 或 /j2se/1.4.2/download.html页面的底部找到下载的链接。否则在使用WS-Security时,可以会抛出java.security.InvalidKeyException: Illegal key size的错误信息。策略文件包括local_policy.jar和US_export_policy.jar文件,将其拷贝到/jre/lib/security目录下。为了方便读者,我们在光盘resources/jce_policy-1_5_0拥有该策略文件的拷贝。你也许会问:为何Sun不把它集成到JDK中去,而单独“损人不利己”地弄一个链接出来给人下载?这是因为每个国家,尤其是美国,对涉及密码的软件产品控制非常严格,在美国国内,很多密码算法长度都作了限制,而且某些算法在某些国家没有申请专利,可以随意使用,而在某些国家却做了明确限制,不准使用,因此Sun必须按照惯例行事。安装SecurityProviderWSS4J使用了BouncyCastle的SecurityProvider,所以需要事先在java.security文件中进行配置,否则运行加密模式的XFire认证时,会抛出以下的出错信息:org.apache.ws.security.WSSecurityException: An unsupported signature or encryption algorithm was used unsupported key在java.security文件中(位于/jre/lib/security目录中)添加BouncyCastleProvider的配置:vider.1=vider.Svider.2=sun.security.rsa.SunRsaSvider.3=ernal.ssl.Pvider.4=vider.SunJCEvider.5=sun.security.jgss.SunPvider.6=com.sun.security.sasl.Pvider.7=vider.BouncyCastleProviderXFire发布包中包含了BouncyCastle SecurityProvider的类包,位于/lib/bcprov-jdk15-133.jar下。必须将bcprov-jdk15-133.jar加入到类路径中。你可以在/display/PENROSE/Installing+Security+Provider中获取更多关于安装BouncyCastle SecurityProvider的帮助。创建密钥对和数字证书签名和加密需要使用到数字证书和密钥对,可以使用JDK提供的KeyTool工具创建密钥对和数字证书。我们分别为服务端和客户端创建RSA密钥对,并生成各自的X509数字证书(包含公钥和数字签名)。服务端和客户端拥有各自的密钥库JKS文件,服务端的密钥库保存服务端的密钥对和客户端的数字证书,而客户端的密钥库保存客户端的密钥对和服务端的数字证书。下面,我们来完成创建服务端和客户端密钥库的工作: 编写一个用于创建RSA密钥对的generateKeyPair.bat批处理文件: rem echo off#接受参数echo alias %1echo keypass %2echo keystoreName %3echo KeyStorePass %4echo keyName %5创建RSA密钥对keytool -genkey -alias %1 -keypass %2 -keystore %3 -storepass %4 -dname cn=%1 -keyalg RSA keytool -selfcert -alias %1 -keystore %3 -storepass %4 -keypass %2 使用私钥进行自签名keytool -export -alias %1 -file %5 -keystore %3 -storepass %4 导出数字证书 编写一个使用generateKeyPair.bat创建服务端和客户端的密钥库的generateKeyStore.bat批处理文件: 下面两行命名分别调用generateKeyPair.bat批处理文件为服务端和客户端生成密钥对call generateKeyPair.bat server serverpass serverStore.jks storepass serverKey.rsa call generateKeyPair.bat client clientpass clientStore.jks storepass clientKey.rsa将服务端的数字证书导入客户端的密钥库keytool -import -alias server -file serverKey.rsa -keystore clientStore.jks -storepass storepass -noprompt将客户端的数字证书导入服务端的密钥库keytool -import -alias client -file clientKey.rsa -keystore serverStore.jks -storepass storepass -noprompt运行该批处理文件后,将分别为服务端和客户端生成一个Java密钥库文件,它们分别拥有一个自己的密钥对和对方的数字证书。我们通过表1对两者密钥库文件的内容进行说明:表1密钥库说明服务端Java密钥库客户端Java密钥库对应密钥库文件serverStore.jksclientStore.jks密钥库密码storepassstorepass库中包含的内容server密钥对、client数字证书client密钥对、server数字证书密钥对别名serverclient密钥对私钥的保护密码serverpassclientpass 将serverStore.jks和clientStore.jks拷贝到/src/META-INF/xfire的目录下,以便后面的实例代码使用。 使用用户名/密码进行身份认证对SOAP报文进行身份认证的方式很多,不过都是通过在SOAP报文头中添加一些安全凭证(Security Token)信息来完成的,主要包括以下一些身份凭证: 用户名/密码; X.509 证书; Kerberos 票据和认证者; SIM 卡的移动设备安全性凭证。 其中用户名/密码是最简单的身份认证方式,它不需要密钥、数字证书,所以也就不需要CA,部署实施简单易行。下面我们就通过例子讲解如何进行基于用户名/密码的SOAP认证。这个实例让客户端提供用户名/密码,服务端验证客户端的身份,而客户端按正常方式接收SOAP响应报文。服务端服务端创建一个applicationContext-ws-security.xml,让BbtForumService拥有用户名/密码的认证功能。代码清单1 applicationContext-ws-security.xml:身份认证Web Service名称负责将STAX流模型的SOAP转换为DOM模型对用户名/密码进行检查UsernameToken指定认证类型指定一个密码回调实现类com.baobaotao.xfire.wss4j.server.UtPasswordHandler由于需要对SOAP进行前置处理,所以必须将STAX流模型的SOAP转换为DOM模型,这通过在处指定一个DOMInHandler来完成。在注册了一个处理SOAP报文的WSS4JInHandler,用于对接收的SOAP报文进行前置处理,与其对应的是WSS4JOutHandler,它对SOAP报文进行后置处理。两者都具有极高的定制性,可以通过配置定制各种加工逻辑,这可以通过合理设置properties属性达到各种加工处理的要求。在处,我们定义了一个action属性,它定义了需要处理的动作,UsernameToken表示进行用户名/密码认证的操作。其它的动作包括Encrypt、Signature、Timestamp、SamlTokenUnsigned等,可以同时设置多个动作,多个动作之间用空格分隔,如Encrypt Signature。不同的动作通过设置配套的其它属性提供相应的操作,我们通过了passwordCallbackClass属性指定一个密码回调实现类来处理UsernameToken密码查询和认证的工作。passwordCallbackClass指定的类必须实现javax.security.auth.callback.CallbackHandler接口,其代码如下所示:代码清单2 UtPasswordHandlerpackage com.baobaotao.xfire.wss4j.server;import java.util.*import javax.security.auth.callback.Callback;import javax.security.auth.callback.CallbackHandler;import org.apache.ws.security.WSConstants;import org.apache.ws.security.WSPasswordCallback;import org.apache.ws.security.WSSecurityException;public class UtPasswordHandler implements CallbackHandler private static final Map pwMockDB = new HashMap();正确用户/密码的模拟数据staticpwMockDB.put(tom, 123456);pwMockDB.put(john, 123456);pwMockDB.put(katty, 123456);pwMockDB.put(mike, 123456);public void handle(Callback callbacks) throws WSSecurityException回调接口方法WSPasswordCallback callback = (WSPasswordCallback) callbacks0;-1:获取回调对象String id = callback.getIdentifer();-2:获取用户名String validPw = (String)pwMockDB.get(id);-3:获取用户对应的正确密码-4:如果是明文密码直接进行判断if(WSConstants.PASSWORD_TEXT.equals(callback.getPasswordType()String pw = callback.getPassword();if(pw = null | !pw.equalsIgnoreCase(validPw)throw new WSSecurityException(password not match);else-5:如果是密码摘要,向回调设置正确的密码(明文密码)callback.setPassword(validPw);PasswordHandle负责根据用户名查询正确的密码,这里,我们通过一个pwMockDB模拟存储用户名密码的数据库,如所示。如果客户端以明文形式发送密码,UtPasswordHandler可以直接判断密码的正确性,如-4所示。反之,如果以摘要的方式发送密码,UtPasswordHandler必须将正确的密码设置到callback中,以便WSS4JInHandler进行判断,如-5所示。这里为明文和密文的密码分别提供了处理逻辑,但一般情况下,密码是以明文还是密文发送是交互双方已经约定好的。你也可以通过扩展XFire的AbstractHandler定义自己的Handler,回调接口会传入MessageContext实例,可以通过MessageContext访问到SOAP中用户名/密码的信息进行认证。客户端现在服务端的Web Service服务已经需要对请求SOAP报文进行用户名/密码的认证了,客户端当然要进行相应的调整,以便在发送SOAP请求报文时添加用户名/密码的信息。代码清单3 BbtForumServiceUTClientpackage com.baobaotao.xfire.wss4j.client;import java.lang.reflect.Proxy;import .MalformedURLException;import java.util.Properties;import org.apache.ws.security.WSConstants;import org.apache.ws.security.handler.WSHandlerConstants;import org.codehaus.xfire.client.Client;import org.codehaus.xfire.client.XFireProxy;import org.codehaus.xfire.client.XFireProxyFactory;import org.codehaus.xfire.security.wss4j.WSS4JOutHandler;import org.codehaus.xfire.service.Service;import org.codehaus.xfire.service.binding.ObjectServiceFactory;import org.codehaus.xfire.util.dom.DOMOutHandler;import com.baobaotao.xfire.server.BbtForumService;public class BbtForumServiceUTClient private static XFireProxyFactory serviceFactory = new XFireProxyFactory();public static void main(String args) Service serviceModel = new ObjectServiceFactory().create(BbtForumService.class);try Web Service地址,注意服务名为BbtForumServiceUTString serviceURL = http:/localhost:8080/baobaotao/service/BbtForumServiceUT;BbtForumService service = (BbtForumService) serviceFactory.create(serviceModel, serviceURL); 获取访问服务的客户端对象Client client = (XFireProxy)Proxy.getInvocationHandler(service).getClient();client.addOutHandler(new DOMOutHandler();添加流模型和DOM模型转换的Handler以下代码添加一个Handler,通过属性对象的设置往SOAP头中添加用户名/密码的凭证Properties properties = new Properties();properties.setProperty(WSHandlerConstants.ACTION, -1动作WSHandlerConstants.USERNAME_TOKEN);properties.setProperty(WSHandlerConstants.PASSWORD_TYPE, -2密码类型WSConstants.PW_DIGEST);properties.setProperty(WSHandlerConstants.USER, client);-3指定用户properties.setProperty(WSHandlerConstants.PW_CALLBACK_CLASS,-4密码回调类UtPasswordHandler.class.getName();client.addOutHandler(new WSS4JOutHandler(properties);添加WSS4JOutHandlerint count = service.getRefinedTopicCount(20);System.out.println(count:+count); catch (MalformedURLException e) e.printStackTrace();服务端在接收添加WS-Security信息的SOAP请求报文前必须进行前置处理,和服务端相对应,客户端在发送SOAP请求报文前进行前置处理,添加WS-Security信息。因此使用DOMOutHandler将DOM转换为STAX的流模型,此外通过定义一个WSS4JOutHandler完成在SOAP头添加用户名/密码信息的操作。在-2处,定义了密码的类型,WSConstants.PW_DIGEST表示密码以摘要方式发送,这可以防止密码的传输安全。设置为WSConstants.PW_TEXT表示密码以明文方式发送。-3指定了一个用户名client,一般情况下,用户的密码保存在文件中或数据库中,因此通过指定一个回调类UtPasswordHandler完成用户密码的获取操作,如-4,回调类必须实现javax.security.auth.callback.CallbackHandler接口,UtPasswordHandler的代码如下所示:代码清单4 UtPasswordHandlerpackage com.baobaotao.xfire.wss4j.client;import java.util.*;import javax.security.auth.callback.Callback;import javax.security.auth.callback.CallbackHandler;import org.apache.ws.security.WSPasswordCallback;public class UtPasswordHandler implements CallbackHandler 客户端用户模拟数据库private static final Map pwMockDB = new HashMap()staticpwMockDB.put(tom, 123456);public void handle(Callback callbacks) WSPasswordCallback callback = (WSPasswordCallback) callbacks0;String id = callback.getIdentifer();callback.setPassword(pwMockDB.get(id);获取用户对应的密码运行代码清单3,通过类似于TcpTrace的工具截取SOAP请求报文,你将可以看到带WS-Security报文头的SOAP报文:clientwOtW+umoWdf/7s7pyJrlFAp2xJo=zJlCTQNCa+jHur2JdJF8Fw=2007-04-09T09:11:05.593Z20报文中粗体的部分为WS-Security的信息,为了简洁,我们特意删除了报文中一些命名空间的内容。元素被导入到SOAP报头中以携带身份信息。wsse:Username用于指定一个用户名,而则用于指定密码。有两种类型的密码:PasswordText和PasswordDigest,PasswordText以明文格式表示密码,而PasswordDigest则被定义为Base64编码的SHA-1散列值。还有两个可选元素和:前者是发送方创建的一个随机值,后者则是一个时间戳。如果和两个元素中至少出现了一个,计算PasswordDigest的算法如下(每次PasswordDigest的值都是不一样的):PasswordDigest = Base64(SHA-1(nonce+created+password)如果没有使用其他的安全机制,PasswordDigest是通过非保密渠道发送用户名和口令的最佳方法。即使使用XML加密对元素进行加密,PasswordText依然可以使用。对SOAP报文进行数字签名使用用户名/密码虽然可以验证SOAP请求报文发送者的身份实现授权访问,但是服务端却无法保证报文在传输过程中没有被篡改黑客可以截取使用了UsernameToken的SOAP报文并在篡改后再发送给服务端,就会使SOAP报文的完整性遭受破坏。此外,仅使用UsernameToken的SOAP,客户端用户可以抵赖自己的操作行为,因为黑客确实可以通过一些手段(如键盘监听、暴力破解等)获取用户的密码。而数字签名则可以解决以上的问题,保证交易的完整性和不可抵赖性。客户端通过私钥对SOAP报文进行数字签名,由于私钥只为个人拥有,因此不可抵赖性得到了保证。数字签名其实是使用私钥对报文的摘要进行加密,只有报文在传输过程中不被篡改,接收端在进行数字签名验证时才可能成功,因此完整性又得到了保证。下面,我们在客户端对请求SOAP进行数字签名,而服务端验证客户端签名的合法性。客户端使用client私钥进行数字签名,服务端使用client的数字证书(包含client的公钥)验证客户端的签名。服务端服务端在验证客户端的签名时,必须访问serverStore.jks中的client数字证书,所以需要进行相应的配置:代码清单5 applicationContext-ws-security.xml:数字签名通过该Handler进行数字签名验证数字签名动作(因为是InHandler所以对应的操作是验证数字签名)Signature验证数字签名需要访问保存着client数字证书的密钥库,通过属性文件提供相应的配置信息。 com/baobaotao/xfire/wss4j/server/insecurity_pertiesinsecurity_perties定义了serverStore.jks的位置以及访问密码,WSS4J使用ponents.crypto.Merlin类作为SecurityProvider。insecurity_perties的内容如下所示:vider=ponents.crypto.Merlinorg.apache.ws.security.crypto.merlin.keystore.type=jks密钥库类型org.apache.ws.security.crypto.merlin.keystore.password=storepassserverStore.jks的访问密码org.apache.ws.security.crypto.merlin.file=META-INF/xfire/serverStore.jks密钥库文件所在位置客户端客户端必须通过注册OutHandler,使用私钥对SOAP报文进行数字签名。客户端的私钥别名为client,存储在clientStore.jks的密钥库中。访问密钥库和私钥都必须提供密码,因此必须进行相应的设置。代码清单6 BbtForumServiceSignClientpackage com.baobaotao.xfire.wss4j.client;public class BbtForumServiceSignClient private static XFireProxyFactory serviceFactory = new XFireProxyFactory();public static void main(String args) Service serviceModel = new ObjectServiceFactory().create(BbtForumService.class);try String serviceURL = http:/localhost:8080/baobaotao/service/BbtForumServiceSign;BbtForumService service =(BbtForumService) serviceFactory.create(serviceModel, serviceURL);Client client = (XFireProxy)Proxy.getInvocationHandler(service).getClient();client.addOutHandler(new DOMOutHandler();Properties properties = new Properties();properties.setProperty(WSHandlerConstants.ACTION, 指定动作为签名WSHandlerConstants.SIGNATURE);数字签名需要访问client私钥,私钥位于密钥库中,通过属性文件提供相应的信息properties.setProperty(WSHandlerConstants.SIG_PROP_FILE, com/baobaotao/xfire/wss4j/client/outsecurity_perties);properties.setProperty(WSHandlerConstants.USER, client);密钥库中密钥对的别名通过密码回调类获得密钥对私密的访问密码properties.setProperty(WSHandlerConstants.PW_CALLBACK_CLASS, PasswordHandler.class.getName();properties.setProperty(WSHandlerConstants.SIG_KEY_ID, IssuerSerial);client.addOutHandler(new WSS4JOutHandler(properties);int count = service.getRefinedTopicCount(20);System.out.println(count:+count); catch (MalformedURLException e) e.printStackTrace();和用户名/密码进行身份认证相似,在进行数字签名时,也需要提供用户名和密码,不过两者截然不同,后者的用户名为密钥库中密钥对的别名,密码为私钥的访问密钥。处的client为clientStore.jks密钥库中客户端密钥对的别名,私钥访问密码通过PasswordHandler获取,如下所示:代码清单7 PasswordHandlerpackage com.baobaotao.xfire.wss4j.client;public class PasswordHandler implements CallbackHandler private static final Map pwMockDB = new Has
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025阳泉市市属国有企业招聘53人笔试参考题库附带答案详解
- 2025辽宁能源集团所属铁法能源公司招聘63人笔试参考题库附带答案详解
- 2025福建龙岩上杭县文化旅游发展有限公司所属企业招聘16人笔试参考题库附带答案详解
- 2025浙江慈溪市诚安燃气服务有限公司招聘10人笔试参考题库附带答案详解
- 2025江苏宜宸产业投资有限公司招聘2人笔试参考题库附带答案详解
- 2025广东省汕特建设集团有限公司招聘专业技术人才4人笔试参考题库附带答案详解
- 2025年国网甘肃省电力公司高校毕业生提前批招聘动态笔试参考题库附带答案详解
- 2025年合肥热电集团春季招聘30人笔试参考题库附带答案详解
- 2025四川内江汉江教育管理有限公司招聘2人笔试参考题库附带答案详解
- 2025中国葛洲坝集团易普力股份有限公司禹州分公司招聘22人(河南)笔试参考题库附带答案详解
- 私密线上招商课件
- 兵团面试题目及答案
- 2025水发集团有限公司招聘216人考试模拟试题及答案解析
- 智慧加油站物联网综合管控平台建设综合解决方案
- 2025年甘肃省公职人员考试时事政治考试试题(附含答案)
- 花岗岩铺设方案
- 2025年护理疼痛试题及答案
- 桥梁工程监理工作实施方案
- 年产5万吨氧化铁新材料(磁性材料及锂电材料)项目报告书
- 服装辅料基础知识培训
- 江苏南京2020-2023年中考满分作文53篇
评论
0/150
提交评论