J2ME使用Socket通过cmwap接入点访问安全HTTPS1 【转】
??? 1 HttpConnection conn = null;
2 InputStream is = null;
3 try {
4 // url: https://ebs.95559.com.cn/corporbank/es_logon.jsp
5 conn = (HttpConnection) Connector.open("http://10.0.0.172:80/corporbank/es_logon.jsp", Connector.READ, true);
6 String host = "ebs.95559.com.cn";
7 conn.setRequestProperty("x-online-host", host);
8 conn.setRequestMethod(HttpConnection.GET);
9
10 int code = conn.getResponseCode();
11 System.out.println("Response Code: " + code);
12
13 is = conn.openDataInputStream();
14
15 System.out.println("Response Stream:");
16 byte[] buf = new byte[128];
17 while (true) {
18 int availSize = is.read(buf, 0, buf.length);
19 if (availSize == -1) {
20 break;
21 }
22 System.out.println(new String(buf, 0, availSize));
23 }
24 } catch (Exception ex) {
25 ex.printStackTrace();
26 } finally {
27 if (is != null) {
28 try {
29 is.close();
30 } catch (IOException ex) {
31 ex.printStackTrace();
32 }
33 }
34
35 if (conn != null) {
36 try {
37 conn.close();
38 } catch (IOException ex) {
39 ex.printStackTrace();
40 }
41 }
42 }
43
此代码的作用是:使用cmwap代理,请求我们制定的页面,并在控制台中输出返回的状态码及内容。很显然,这是一种普通的cmwap连接方式,并没有考虑https因素的加入,输出的结果也在意料之内:
Response Code: 502
Response Stream:
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">
<wml><card>
<p><do type="prev" name="Back" label="Back"><prev/></do>Connection to host failed. Check your settings and try again. If the pro
blem persists contact your operator.</p></card></wml>
?
?
原因分析:我们要请求的是安全HTTP,端口443,而在我们的代码中并没有体现出我们要连接HTTPS的意图,我们只是告诉了cmwap代理我们要连接地址“ebs.95559.com.cn/corporbank/es_logon.jsp”,而并没有告诉cmwap代理我们所要访问的地址是基于HTTPS的,所以cmwap代理会按照地址“http://ebs.95559.com.cn/corporbank/es_logon.jsp”去连接,恰好这个地址是不支持HTTP:80的,cmwap代理返回了网关错误。?
尝试方法二:
针对以上设想,我们将代码修改一下,想方设法让cmwap代理知道我们要访问的目标地址属于HTTPS:443。
修改程序的第6行,使其变成:
String host = "ebs.95559.com.cn:443";
运行,控制台还是输出了以下错误:
Response Code: 500
Response Stream:
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">
<wml><card>
<p><do type="prev" name="Back" label="Back"><prev/></do>Your request for a service could not be fulfilled. Please try again or c
ontact your operator if the problem persists. </p></card></wml>
?
原因分析:不详。?
尝试方法三:
以上两种方法都行不通,有没有可能cmwap代理服务器开通了SSL端口,来让应用程序通过此端口来访问HTTPS呢?
将代码第5行修改如下:
conn = (HttpConnection) Connector.open("https://10.0.0.172:443/corporbank/es_logon.jsp", Connector.READ, true);
模拟器长时间没有响应。
原因分析:一般手机自带的浏览器都支持访问HTTPS,而手机设置的cmwap代理地址都是10.0.0.172:80。所以可以肯定的是手机是可以通过10.0.0.172:80这个代理访问HTTPS而并不是10.0.0.172:443。上网查了资料,证明移动针对cmwap代理只开通了80 端口,而并没有开通443端口。
尝试方法四(成功):
经过了以上三次失败,我不得不好好静下心来想想解决方法。我想到了使用OTA的方式,让PC连接到GPRS上进行调试。首先使用数据线连接电脑和手机,将电脑的本地连接禁用,把手机当猫用,创建基于手机拨号的网络连接,输入号码“*99#”,拨号,连接。给浏览器设置好代理 10.0.0.172:80后,能够正常浏览HTTPS地址。我忽然想到,既然HttpConnection不能够正常通过cmwap连接HTTPS,那我使用Socket模拟HTTP请求能成功吗?带着这个疑问,我开始进行准备:
必备工具:
Wireshark或HttpWatch或Openware Simulator
最开始我是使用Firefox+Wireshark拦截80端口的包的,但是浏览器向服务器发出SSL Hello后传输的内容都会被加密,Wireshark所看到的都是密文,相当的不方便。如图:
后来我发现,Openware Simulator提供浏览器,且本身就提供了类似于Wireshark的功能,而且可以截获到HTTP层所传输的内容,能够很清楚的看见客户端与服务器端来往的过程。所以,我们以Openware Simulator的截图作为说明。Openware Simulator下载地址:这里(免费,需要邮件注册)
还可以使用HttpWatch 6.0,新版HttpWatch已经可以作为Firefox的扩展嵌入。不过这个要收大洋,还是Openware Simulator来得直接一些。
实现方法:
打开Openwave V7 Simulator,在模拟器地址栏输入网址,截图如下:
通过右边的控制台输出窗口,我们可以很清楚的看到Openware Simulator通过向cmwap代理所发出的请求格式。并且,通过Socket连接,是不需要添加“x-online-host”请求头的。
既然HttpConnection行不通,我们自己就使用Socket实现Http连接,向cmwap代理发出请求。
此处要先说明以下两点:
1、J2ME中的SocketConnection是MIDP 2.0的可选包,并不是每个手机都提供Socket的支持;
2、我们必须使用Socket连接cmwap代理10.0.0.172:80,而MIDP 2.0对Socket访问80端口加了限制,在真机上使用必须得使用证书签署生成的JAD,否则会抛出安全异常。
在此我不按照Openware Simulator控制台中显示的连接顺序(先Connect后Get)进行连接,使用Openware Simulator只是证明我想法的可行性,我将直接使用Get+完整URL的方式进行代码的编写。
?