- 浏览: 265340 次
- 性别:
- 来自: 香港
文章分类
最新评论
-
xinglianxlxl:
对我有用,谢谢
Java Axis-1.4 调用 .net webserice(手动下载证书和程序自动装载证书)) -
July01:
推荐用StratoIO打印控件,支持网页、URL、图片、PD、 ...
利用Applet进行Web打印 -
njitjiang:
完美,正在想这个问题怎么处理呢,多谢。
JasperReport 根据内容动态调整报表行高 -
luoyonghui55:
你这个要是能再写一些注释说明就更好了。
oracle 利用 lead 、lag 查询已有记录的下一条、上一条记录 -
guang.027:
很不错,不错,试试...
PKIX path building failed 的问题
Java 调用.net发布的Web service可以通过众多的java lib来实现
本文选择Axis-1.4来说明如何调用.net webservice
(一)通过WSDL文件生成Java代码
1.先得到.net webservice的WSDL文件,可以这样得到:https://xxx.com.hk/bcmedservice/BCWebServices.asmx?WSDL或者https://xxx.com.hk/bcmedservice/BCWebServices.asmx?WSDL
2.通过org.apache.axis.wsdl.WSDL2Java类结合得到的WSDL文件生成Java代码。因生成的文件较多,不便分析,我将它改成了三个文件,若.net那边没有封装参数和结果,只需要一个文件即可。文件代码如下:
1)
import java.security.Security;
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
public class BCWebService {
public static String checkMember(java.lang.String medicalGroup,
java.lang.String requestTicket, java.lang.String userID,
java.lang.String password, java.lang.String claimDate,
java.lang.String memberKey1, java.lang.String memberKey2,
java.lang.String doctorCode) {
String endpoint = "https://xxx.com.hk/bcmedservice/BCWebServices.asmx";
try {
//以下是调用https需要用到的安全证书,下面会介绍如何下载安全证书
System.setProperty("javax.net.ssl.keyStore", "D:/xxx/jssecacerts");
Service service = new Service();
Call call = (Call) service.createCall();
call.setTargetEndpointAddress(new java.net.URL(endpoint));
call.setUseSOAPAction(true);
call.setSOAPActionURI("https://xxx.com.hk/bcmedservice/Check_Member_Eligibility");
call.setEncodingStyle(null);
call.setProperty(org.apache.axis.client.Call.SEND_TYPE_ATTR,
Boolean.FALSE);
call.setProperty(org.apache.axis.AxisEngine.PROP_DOMULTIREFS,
Boolean.FALSE);
call.setOperationName(new javax.xml.namespace.QName(
"https://xxx.com.hk/bcmedservice/",
"Check_Member_Eligibility"));
call.addParameter(new javax.xml.namespace.QName(
"https://xxx.com.hk/bcmedservice/",
"objParameter"), new javax.xml.namespace.QName(
"https://xxx.com.hk/bcmedservice/",
"Check_Member_Eligibility"), InputParameter.class,
javax.xml.rpc.ParameterMode.IN);
call.setReturnType(new javax.xml.namespace.QName(
"https://xxx.com.hk/bcmedservice/",
"Check_Member_EligibilityResponse"));
call.setReturnClass(OutputResponse.class);
OutputResponse or2 = (OutputResponse)call.invoke(new java.lang.Object[] { new InputParameter(medicalGroup, requestTicket, userID, password,claimDate, memberKey1, memberKey2, doctorCode) });
if (or2 != null) {
StringBuffer sb = new StringBuffer();
sb.append("<OutputResponse><RequestTicket>");
sb.append(or2.getRequestTicket());
sb.append("</RequestTicket><ResponseTicket>");
sb.append(or2.getResponseTicket());
sb.append("</ResponseTicket><ResponseCode>");
sb.append(or2.getResponseCode());
sb.append("</ResponseCode><ResponseMessageEng>");
sb.append(or2.getResponseMessageEng());
sb.append("</ResponseMessageEng><ResponseMessageChi>");
sb.append(or2.getResponseMessageChi());
sb.append("</ResponseMessageChi><TechnicalRemarks>");
sb.append(or2.getTechnicalRemarks());
sb.append("</TechnicalRemarks><InsuredName>");
sb.append(or2.getInsuredName());
sb.append("</InsuredName><GPCopayAmt>");
sb.append(or2.getGPCopayAmt());
sb.append("</GPCopayAmt><GPXMedAmt>");
sb.append(or2.getGPXMedAmt());
sb.append("</GPXMedAmt><SPCopayAmt>");
sb.append(or2.getSPCopayAmt());
sb.append("</SPCopayAmt><SPXMedAmt>");
sb.append(or2.getSPXMedAmt());
sb.append("</SPXMedAmt></OutputResponse>");
return sb.toString();
} else {
return null;
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
其中的InputParameterl类和OutputResponse类是由WSDL2Java生成的
(二)调用非 SSL 发布的 webservice
若调用非 SSL 发布的 webservice,只需要将
System.setProperty("javax.net.ssl.trustStore", "D:/xxx/jssecacerts");去掉即可
(三)调用SSL发布的webservice
这种情况需要下载安全证书,可以通过运行一个java类来实现,具体参考我的另外一篇博客:
PKIX path building failed 的问题,请注意证书的应用要重新启动应用服务器(如tomcat server)。因前面的方法是静态的方法,不是动态过程中能加载这个证书的。
证书得到后,按照上面的BCWebservice.java就可以调用.net webServcie了。有一个问题需要提到的是,如果安全证书经常更新变化,又不想每次也跟着重新下载证书,希望程序自动取验证。我当初想到,这还不容易,通过程序运行刚才下载证书的代码不就可以重新生成证书了?问题是,就算是能下载到新的证书,这个新的也用不上。除非你重启web服务器,或重新加载调用webservice的项目,若是Application,也需要关闭,重新开启程序才可以。因为这个证书是在程序第一次运行时加载的,而且axis会将这个东西缓存起来,缓存起来的东西叫SSLSocketFactory 的一个实例。而这个SSLSocketFactory 的初始化是Axis自动执行的。
我现在希望是应用程序不需重新启动,希望证书的下载和验证都通过程序来执行,怎么做?就是在运行时能重新加载和验证新的证书SocketFactory被实例化之前,应该已经验证了证书,否则它无法访问SSL的webservice。既然这样,能否自己初始化SocketFacotry呢,那是肯定的。可以写一个类重新实现SocketFactory,但要遵循一些规则。一下是一个示例:
public class MyCustomSSLSocketFactory extends JSSESocketFactory implements SecureSocketFactory {
/* local keystore password */
private static String MY_KEYSTORE_PASSWORD = "changeit";
/* local keystore file (contains the self-signed certificate from the server */
private static String RESOURCE_PATH_TO_KEYSTORE = "D:/UTA/DOC_E_Health_XML/Keystore/bluecrossCertificate";
/**
* Constructor MyCustomSSLSocketFactory
*
* @param attributes
*/
public MyCustomSSLSocketFactory(Hashtable attributes) {
super(attributes);
}
/**
* Read the keystore, init the SSL socket factory
*
* This overrides the parent class to provide our SocketFactory implementation.
* @throws IOException
*/
protected void initFactory() throws IOException {
try {
SSLContext context = getContext();
sslFactory = context.getSocketFactory();
} catch (Exception e) {
e.printStackTrace();
if (e instanceof IOException) {
throw (IOException) e;
}
throw new IOException(e.getMessage());
}
}
/**
* Gets a custom SSL Context.
* This is the main working of this class. The following are the steps that make up our
* custom configuration:
*
* 1. Open our keystore file using the password provided
* 2. Create a KeyManagerFactory and TrustManagerFactory using this file
* 3. Initialise a SSLContext using these factories
*
* @return SSLContext
* @throws WebServiceClientConfigException
* @throws Exception
*/
protected SSLContext getContext() throws Exception {
String host="xxx.com.hk"; //这是你要访问的WEbservice的域名
try
{
// create required keystores and their corresponding manager objects
/*KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(keystoreFile, keystorepass);
KeyManagerFactory kmf =
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(keyStore, keystorepass);
TrustManagerFactory tmf =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keyStore);
// congifure a local SSLContext to use created keystores
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());
*/
char[] passphrase=MY_KEYSTORE_PASSWORD.toCharArray();
File file = new File(RESOURCE_PATH_TO_KEYSTORE);
if (file.isFile() == false) {
char SEP = File.separatorChar;
File dir = new File(System.getProperty("java.home") +SEP
+ "lib" + SEP + "security");
file = new File(dir, "jssecacerts");
if (file.isFile() == false) {
file = new File(dir, "cacerts");
}
}
InputStream in = new FileInputStream(file);
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(in, passphrase);
in.close();
SSLContext context = SSLContext.getInstance("TLS");
KeyManagerFactory kmf =
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, passphrase);
TrustManagerFactory tmf =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ks);
X509TrustManager defaultTrustManager = (X509TrustManager)tmf.getTrustManagers()[0];
SavingTrustManager tm = new SavingTrustManager(defaultTrustManager);
context.init(null, new TrustManager[] {tm}, null);
SSLSocketFactory factory = context.getSocketFactory();
SSLSocket socket = (SSLSocket)factory.createSocket(host, 443);
socket.setSoTimeout(10000);
try {
socket.startHandshake();
socket.close();
System.out.println();
System.out.println("No errors, certificate is already trusted");
} catch (SSLException e) {
System.out.println();
System.out.println("***************Succeed to regenerate certificate***************");
//e.printStackTrace(System.out);
}
X509Certificate[] chain = tm.chain;
if (chain == null) {
System.out.println("Could not obtain server certificate chain");
}
MessageDigest sha1 = MessageDigest.getInstance("SHA1");
MessageDigest md5 = MessageDigest.getInstance("MD5");
for (int i = 0; i < chain.length; i++) {
X509Certificate cert = chain[i];
sha1.update(cert.getEncoded());
md5.update(cert.getEncoded());
System.out.println();
}
int k=0;
X509Certificate cert = chain[k];
String alias = "xxx.com.hk" + "-" + (k + 1);
ks.setCertificateEntry(alias, cert);
OutputStream out = new FileOutputStream(RESOURCE_PATH_TO_KEYSTORE);
ks.store(out, passphrase);
out.close();
in = new FileInputStream(new File(RESOURCE_PATH_TO_KEYSTORE));
ks.load(in,passphrase);
in.close();
kmf.init(ks, passphrase);
tmf.init(ks);
context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());
return context;
}
catch (Exception e)
{
throw new Exception("Error creating context for SSLSocket!", e);
}
}
private static class SavingTrustManager implements X509TrustManager {
private final X509TrustManager tm;
private X509Certificate[] chain;
SavingTrustManager(X509TrustManager tm) {
this.tm = tm;
}
public X509Certificate[] getAcceptedIssuers() {
throw new UnsupportedOperationException();
}
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
throw new UnsupportedOperationException();
}
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
this.chain = chain;
tm.checkServerTrusted(chain, authType);
}
}
}
生成后我怎么让AXis用它呢,之需在BCWebservice.java中增加如下语句:
AxisProperties.setProperty("axis.socketSecureFactory","com.xxx.webservice.MyCustomSSLSocketFactory");
问题到这儿还没结束,虽然我重写了SocketFactory,但是这个SocketFactory仍然被SocketFactoryFactory单例化了,所以还得改写SocketFactoryFactory,但这个时候不可以自定义,必须完全替换掉axis库中的 这个类,因为axis没法在运行时变换这个SocketFactoryFactory类的实例。替换的类如下:
红色部分为修改的代码
public class SocketFactoryFactory {
/** Field log */
protected static Log log =
LogFactory.getLog(SocketFactoryFactory.class.getName());
/** socket factory */
private static Hashtable factories = new Hashtable();
private static final Class classes[] = new Class[] { Hashtable.class };
static {
AxisProperties.setClassOverrideProperty(SocketFactory.class,
"axis.socketFactory");
AxisProperties.setClassDefault(SocketFactory.class,
"org.apache.axis.components.net.DefaultSocketFactory");
AxisProperties.setClassOverrideProperty(SecureSocketFactory.class,
"axis.socketSecureFactory");
AxisProperties.setClassDefault(SecureSocketFactory.class,
"org.apache.axis.components.net.JSSESocketFactory");
}
/**
* Returns a copy of the environment's default socket factory.
*
* @param protocol Today this only supports "http" & "https".
* @param attributes
*
* @return
*/
public static synchronized SocketFactory getFactory(String protocol,
Hashtable attributes) {
SocketFactory theFactory = (SocketFactory)factories.get(protocol);
Object objects[] = new Object[] { attributes };
if (protocol.equalsIgnoreCase("http")) {
if(theFactory==null)
theFactory = (SocketFactory)
AxisProperties.newInstance(SocketFactory.class, classes, objects);
} else if (protocol.equalsIgnoreCase("https")) {
System.out.println();
System.out.println("*********get a new SocketFacotory instance***********");
return (SecureSocketFactory)
AxisProperties.newInstance(SecureSocketFactory.class, classes, objects);
}
if (theFactory != null) {
factories.put(protocol, theFactory);
}
return theFactory;
}
}
最终的BCWebserivce.java如下:
import java.security.Security;
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
public class BCWebService {
public static String checkMember(java.lang.String medicalGroup,
java.lang.String requestTicket, java.lang.String userID,
java.lang.String password, java.lang.String claimDate,
java.lang.String memberKey1, java.lang.String memberKey2,
java.lang.String doctorCode) {
String endpoint = "https://xxx.com.hk/bcmedservice/BCWebServices.asmx";
try {
AxisProperties.setProperty("axis.socketSecureFactory","com.xxx.webservice.MyCustomSSLSocketFactory");
Service service = new Service();
Call call = (Call) service.createCall();
call.setTargetEndpointAddress(new java.net.URL(endpoint));
call.setUseSOAPAction(true);
call.setSOAPActionURI("https://xxx.com.hk/bcmedservice/Check_Member_Eligibility");
call.setEncodingStyle(null);
call.setProperty(org.apache.axis.client.Call.SEND_TYPE_ATTR,
Boolean.FALSE);
call.setProperty(org.apache.axis.AxisEngine.PROP_DOMULTIREFS,
Boolean.FALSE);
call.setOperationName(new javax.xml.namespace.QName(
"https://xxx.com.hk/bcmedservice/",
"Check_Member_Eligibility"));
call.addParameter(new javax.xml.namespace.QName(
"https://xxx.com.hk/bcmedservice/",
"objParameter"), new javax.xml.namespace.QName(
"https://xxx.com.hk/bcmedservice/",
"Check_Member_Eligibility"), InputParameter.class,
javax.xml.rpc.ParameterMode.IN);
call.setReturnType(new javax.xml.namespace.QName(
"https://xxx.com.hk/bcmedservice/",
"Check_Member_EligibilityResponse"));
call.setReturnClass(OutputResponse.class);
OutputResponse or2 = (OutputResponse)call.invoke(new java.lang.Object[] { new InputParameter(medicalGroup, requestTicket, userID, password,claimDate, memberKey1, memberKey2, doctorCode) });
if (or2 != null) {
StringBuffer sb = new StringBuffer();
sb.append("<OutputResponse><RequestTicket>");
sb.append(or2.getRequestTicket());
sb.append("</RequestTicket><ResponseTicket>");
sb.append(or2.getResponseTicket());
sb.append("</ResponseTicket><ResponseCode>");
sb.append(or2.getResponseCode());
sb.append("</ResponseCode><ResponseMessageEng>");
sb.append(or2.getResponseMessageEng());
sb.append("</ResponseMessageEng><ResponseMessageChi>");
sb.append(or2.getResponseMessageChi());
sb.append("</ResponseMessageChi><TechnicalRemarks>");
sb.append(or2.getTechnicalRemarks());
sb.append("</TechnicalRemarks><InsuredName>");
sb.append(or2.getInsuredName());
sb.append("</InsuredName><GPCopayAmt>");
sb.append(or2.getGPCopayAmt());
sb.append("</GPCopayAmt><GPXMedAmt>");
sb.append(or2.getGPXMedAmt());
sb.append("</GPXMedAmt><SPCopayAmt>");
sb.append(or2.getSPCopayAmt());
sb.append("</SPCopayAmt><SPXMedAmt>");
sb.append(or2.getSPXMedAmt());
sb.append("</SPXMedAmt></OutputResponse>");
return sb.toString();
} else {
return null;
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
发表评论
-
Axis 运行时动态选择 证书(select a certifiate at runtime)
2010-02-26 14:34 1701目 錄 The Motivation Th ... -
oracle webservice
2010-01-22 14:22 1734Oracle stored procedure调用web se ... -
实现安全的AXIS Web服务
2009-11-16 12:34 1738http://www.ibm.com/developerwor ... -
ORA-29541: class SYS.oracle/jpub/runtime/dbws/DbwsProxy could not be resolved
2009-11-13 17:17 5870在oracle10.1.2中用function调用webser ... -
webservice over https
2009-11-03 11:46 1653import org.apache.axis.client.C ... -
PKIX path building failed 的问题
2009-11-03 09:52 19355在执行webservice的过程中,出现如下异常: java ...
相关推荐
"Axis-1.4.jar" 是一个用于Java的Web服务框架的重要组件,它主要用于构建和部署SOAP(简单对象访问协议)服务。这个JAR(Java Archive)文件是Apache Axis库的一部分,版本为1.4。Apache Axis是一个开源项目,旨在...
axis-jaxrpc-1.4.jar jaxrpc.jar webservice java工具类jar包。
Axis-1.4是Apache软件基金会开发的一个开源Web服务框架,它主要用于构建和部署SOAP(简单对象访问协议)服务。这个框架在Web服务领域扮演着重要角色,因为它简化了服务的创建、测试和部署过程。在本文中,我们将深入...
android 移动开发 jar包 下载
标题“axis-jaxrpc1.4”所指的是一款名为Axis的Java XML Web服务框架中的一个组件,即JAX-RPC(Java API for XML-based Remote Procedure Calls)的1.4版本。Axis是Apache软件基金会开发的一个开源项目,主要用于...
标题中的"axis.jar"和"axis-saaj-1.4.jar"是两个重要的Java库文件,它们在Web服务开发中扮演着核心角色。本文将详细介绍这两个库以及它们与Web服务的关系。 首先,让我们深入了解Axis。Axis是Apache软件基金会的一...
这个"axis-1.4.zip"压缩包包含了Axis1.4版本的核心组件和其他必要的库文件,它们是开发和调用Web服务的重要工具。接下来,我们将深入探讨这些组件以及它们在Web服务中的作用。 1. **Axis1.4.jar**:这是Axis框架的...
这表明文件axis-1.4_1.jar不仅可能包含了编译后的Java字节码,也可能包括原始的.java源代码,这对于学习、调试和自定义Axis库的行为至关重要。源代码提供了深入理解内部工作原理的机会,而不仅仅是使用预编译的二...
标题“wsdaix-1.1-axis-1.4-bin”揭示了这是一个关于WS-DAI(Web Services Distributed Access Interface)的软件包,版本为1.1,与Apache Axis 1.4集成。Apache Axis是Java平台上的一个开源SOAP(简单对象访问协议...
- **创建服务**:使用Axis2提供的工具,如WSDL2Java,可以从WSDL(Web Services Description Language)文件自动生成服务端代码。 - **部署服务**:将服务打包成aar(Axis2 Archive)文件,然后通过管理控制台或...
java axis 调用 wsdl 所需要的jar,包含(javax.wsdl、commons-logging、commons-discovery-0.2、axis-1.4、activation、jaxrpc、mail、fastjson-1.1.37)
标题中的"axis-bin-1_4.zip"是一个与 Axis1 相关的压缩包,Axis1 是一个开源的 Java 库,主要用于创建、部署和使用 Web Services。这个版本(1.4)是 Axis 的一个稳定版本,包含了 Axis 框架的可执行文件和其他必要...
官方版本,亲测可用
标题中的"axis-1.4-sources.jar.zip"是一个压缩包文件,其中包含了Axis库的1.4版本的源代码。Axis是一个开放源代码的Java框架,主要用于构建Web服务和客户端应用程序,它由Apache软件基金会开发和维护。这个特定的...
"Axis-bin-1.4.rar" 是一个包含 Axis 1.4 版本的压缩包文件,Axis 是一个广泛使用的开放源代码Java Web服务开发框架。这个版本的发布旨在为开发者提供创建、部署和管理Web服务的工具和库。下面我们将深入探讨 Axis ...
使用 Axis2 Codegen Wizard,你可以导入 WSDL 文件,它会根据文件内容自动生成服务接口、实现类和客户端调用代码。 2. **服务端代码生成**:通过此插件,你可以生成 Axis2 服务骨架,包含服务类和服务配置文件。...
标题中的“整合axis-bin1.4+activation.jar+mail.jar.zip”表明这是一个关于 Axis1.4 Web服务框架的集成包,包含了Axis运行时所需的activation.jar和mail.jar两个关键的Java库。Axis是Apache软件基金会开发的一个...
在标题和描述中提到的"axis-bin-1_4.zip"和"Axis1.4-bin"是指 Axis 1.4 的二进制发行版,这个版本的AXIS包含了运行和开发Web服务所需的所有必要组件。"axis-1_4.rar"可能是同一版本的另一种压缩格式,而"axis-bin-_...