首先是服务端如何支持https的问题,步骤如下。
1、生成服务端证书,cmd命令:
keytool -genkey -alias tomcat -keyalg RSA
或者
keytool -genkey -alias jboss -keyalg RSA
按照提示输入一些信息,如果是本机调试,用户名最好输入localhost,否则会出现不匹配异常。
完成后,系统默认把文件放在我的文档里面,名字默认是.keystore。
把文件复制到jboss-5.1.0.GA\server\default\conf下面。
2、在jboss-5.1.0.GA\server\default\deploy\jbossweb.sar\打开server.xml,找到如下:
<!-- SSL/TLS Connector configuration using the admin devl guide keystore-->
<Connector protocol="HTTP/1.1" SSLEnabled="true"
port="443" address="${jboss.bind.address}"
scheme="https" secure="true" clientAuth="false"
keystoreFile="${jboss.server.home.dir}/conf/.keystore"
keystorePass="123456" sslProtocol = "TLS" />
jboss默认有这些,但是注释了,如果没有就添加进去。需要注意下面几个属性值:
port是端口号,默认是8443。
keystoreFile="${jboss.server.home.dir}/conf/.keystore"是keystore文件路径。keystorePass是提示中输入的密码。
3、将系统部署后,启动,浏览器中输入https://localhost:443/projectName
理论上会提示证书不安全,点通过、继续、忽略之类的一个提示,就可以访问了。
同时不影响原来的http://localhost:8080/projectName访问。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
然后是使用httpClient如何访问的问题。
使用https访问时,需要证书验证的。https也是通过证书验证的方式使的所提供的服务更具有安全性。上面的浏览器能够直接访问,是因为浏览器能够自动处理证书的问题,使用httpClient访问https时,只能人为的去处理证书了。有两种方式。
一、第一个是通过浏览器导出证书.cer文件,导入到在httpClient所运行的jdk中,jdk信任该证书后,就可以访问了。
二、将服务端的.keystore文件拿到客户端,程序中通过下面两行来手动信任该证书。
System.setProperty("javax.net.ssl.trustStore", "D:/B/.keystore");
System.setProperty("javax.net.ssl.trustStorePassword","123456");;
~~~~~~~~~~~~~~~~~~
第二种方式只能用于自身调试,因为在系统实际运行中,客户端不可能实时的去拿服务端的.keystore文件。详细介绍一下第一种方式。
1、通过浏览器导出证书。
在浏览器中输入https://localhost:443/projectName,根据提示导出证书。
操作过程中,发现ie8找不到导出的按钮,我用的是filefox,输入地址后,会看到证书不信任提示,按照提示一步步导出,“添加例外——查看——详细信息——导出”,保存类型选择“X509含链证书(PEM)”,即后缀为.crt
打开crt文件,选择“详细信息——复制到文件——一顿下一步”,生成.cer文件。
2、将证书导入到jdk中。
cmd中进入到jdk1.6.0_21\jre\lib\security文件夹中,命令:
keytool -import -noprompt -keystore cacerts -storepass changeit -alias zhy0105 -file D:/B/abcd.cer
提示输入密码时,密码输入:changeit
zhy0105是自定义名称,最后是证书cer文件的全路径。操作成功后会提示:“认证已添加至keystore中”。
3、注意问题。
(1)第一步会因为浏览器的不同和版本不同会有所偏差,上面这个过程只是针对于firefox,还不知道点几。据说有的浏览器可以直接导出.cer文件。
(2)注意jdk的路径:jdk1.6.0_21\jre\lib\security,是jdk下面的jre,不是和jdk平级的那个jre文件夹。别搞错了...
(3)一定要保证导入证书的jdk就是myeclipse中所配置的jdk,myeclipse中默认的jdk是它本身自带的。
如果在myeclipse中用本身自带的jdk运行httpClient,导入证书的jdk是自己安装的。运行肯定会报错,异常我贴在最下面。证书导入成功,httpClient还是访问不了https,这个问题困扰了我三天。
(4)Window7中,如果jdk安装在了c盘,系统默认是不允许修改文件的,cmd中导入证书时会提示拒绝访问,需要在文件夹中的文件属性里面修改一下权限,在执行就可以了。
~~~~~~~~~~~~~~~~~~~~~~~
以上问题处理完后,程序中就直接按照平时访问http的代码来写就可以了。
贴个以post方式访问并且带附件上传的样例
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.httpclient.methods.multipart.StringPart;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.log4j.Logger;
public class HttpsUtils {
private static final Logger log = Logger.getLogger(HttpsUtils.class);
public static void main(String[] args) throws FileNotFoundException {
String reqURL = "https://xpa-ag.huawei.com/Service/LoginServlet2.jsp";
Map<String, String> params = new HashMap<String, String>();
params.put("uid", "03B70CC19E8595F568DC950A1D2BD128");
params.put("password", "3301CC07C2E136070E3FAC012A132109");
sendSSLPostRequest(reqURL, params);
}
public static String sendSSLPostRequest(String reqURL, Map<String, String> params) {
String result = null;
HttpClient httpClient = new HttpClient();
PostMethod method = new PostMethod(reqURL);
Part[] parts = new Part[params.size()];
Iterator<Map.Entry<String, String>> it = params.entrySet().iterator();
int i = 0;
while (it.hasNext()) {
Map.Entry<String, String> entry = it.next();
parts[i++] = new StringPart(entry.getKey(), entry.getValue());
}
method.setRequestEntity(new MultipartRequestEntity(parts, method.getParams()));
// 使用系统提供的默认的恢复策略
method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler());
try {
// 执行method
int statusCode = httpClient.executeMethod(method);
if (statusCode != HttpStatus.SC_OK) {
System.err.println("Method failed: " + method.getStatusLine());
}
// 读取内容
byte[] responseBody = method.getResponseBody();
// 处理内容
result = new String(responseBody);
System.out.println(result);
} catch (HttpException e) {
// 发生致命的异常,可能是协议不对或者返回的内容有问题
log.error(e.getMessage());
e.printStackTrace();
} catch (IOException e) {
// 发生网络异常
log.error(e.getMessage());
e.printStackTrace();
} finally {
// 释放连接
method.releaseConnection();
}
return result;
}
}
另外,如果系统测试所部署的服务器是linux,和开发环境中还有中转服务器的话,把下面这一行放在httpClient对象定义之后就行了。
httpClient.getHostConfiguration().setProxy("10.100.XX.XXX",8080);
转自:http://from-null.iteye.com/blog/859795