回:HttpClient模擬登録12306チケット購入サイト
17209 ワード
まず12306のウェブサイトの接頭辞は“https://” SSLで暗号化されていることを示します。
HttpClientで送信要求をシミュレートする場合、URLに対して「https」を使用する場合、証明書の問題を解決するには、次の2つの解決策があります.
a.証明書を信頼させる.
関連資料を探すとき、この方法はちょっと面倒で、最後に試していません.興味のある友达は試してみてください.
b.httpClientを使用する場合、サーバ証明書が信頼できるかどうかを検出しない
HttpClientクラスを拡張すると、すべての証明書が自動的に受信されるため、セキュリティ上の問題があります.この方法を使用する前に、システムのセキュリティ要件をよく考慮してください.
具体的な手順は次のとおりです.
•カスタムソケットファクターを提供します.このカスタムクラスはインタフェースを実装する必要があります
org.apache.commons.httpclient.protocol.SecureProtocolSocketFactoryは、インタフェースを実装するクラスでカスタムを呼び出す
X509TrustManager(test.MyX509TrustManager)
•orgを作成する.apache.commons.httpclient.protocol.Protocolのインスタンスで、プロトコル名とデフォルトのポート番号を指定します.
Protocol myhttps = new Protocol("https", new MySecureProtocolSocketFactory (), 443);
•先ほど作成したhttpsプロトコルオブジェクトの登録
Protocol.registerProtocol("https ", myhttps);
具体的なコードは以下の通りです.
次はhttpClientの実装クラスです.
シミュレーションリクエストのクラスが出てきましたが、これからシミュレーションログインを行い、ログイン前に12306自身がどのようにリクエストをコミットし、どのパラメータがバックグラウンドに含まれているかを知る必要があります.firebugで簡単に見つけることができます.
12306ログイン前に「https://dynamic.12306.cn/otsweb/loginAction.do?method=loginAysnSuggest」が呼び出され、バックグラウンドには次のようなJSONメッセージが返されます.
{"loginRand":"652","randError":"Y"}
randErrorが「Y」の場合、フォームFORMがコミットされ、loginRandの値がフォーム内の非表示ドメインに初期化され、パラメータとしてバックグラウンドに渡されます.
最後のステップはパラメータの接合です.具体的な操作コードは次のとおりです.
URLはすべてプロファイルの中にあり、大体以下の通りです.
戻ってきたHTMLで、自分の名前を見たら、ログインに成功したということになります.みんながまた何かしたい動作があれば、みんなの想像力を発揮することができます.
勉強としてしか使いません!
変換元:http://www.cnblogs.com/lmeteor/archive/2012/09/27/2705458.html
HttpClientで送信要求をシミュレートする場合、URLに対して「https」を使用する場合、証明書の問題を解決するには、次の2つの解決策があります.
a.証明書を信頼させる.
関連資料を探すとき、この方法はちょっと面倒で、最後に試していません.興味のある友达は試してみてください.
b.httpClientを使用する場合、サーバ証明書が信頼できるかどうかを検出しない
HttpClientクラスを拡張すると、すべての証明書が自動的に受信されるため、セキュリティ上の問題があります.この方法を使用する前に、システムのセキュリティ要件をよく考慮してください.
具体的な手順は次のとおりです.
•カスタムソケットファクターを提供します.このカスタムクラスはインタフェースを実装する必要があります
org.apache.commons.httpclient.protocol.SecureProtocolSocketFactoryは、インタフェースを実装するクラスでカスタムを呼び出す
X509TrustManager(test.MyX509TrustManager)
•orgを作成する.apache.commons.httpclient.protocol.Protocolのインスタンスで、プロトコル名とデフォルトのポート番号を指定します.
Protocol myhttps = new Protocol("https", new MySecureProtocolSocketFactory (), 443);
•先ほど作成したhttpsプロトコルオブジェクトの登録
Protocol.registerProtocol("https ", myhttps);
具体的なコードは以下の通りです.
package org.study.meteor.ticket.util;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.SocketFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.commons.httpclient.ConnectTimeoutException;
import org.apache.commons.httpclient.params.HttpConnectionParams;
import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;
/**
* MySecureProtocolSocketFactory.java.java Create on 2012-9-26 1:15:03
*
*
* Copyright (c) 2012 by MTA.
*
* @author lmeteor
* @Email [email protected]
* @description socket factory
* @version 1.0
*/
public class MySecureProtocolSocketFactory implements
SecureProtocolSocketFactory
{
private SSLContext sslcontext = null;
private SSLContext createSSLContext()
{
SSLContext sslcontext = null;
try
{
sslcontext = SSLContext.getInstance("SSL");
sslcontext.init(null, new TrustManager[]
{ new TrustAnyTrustManager() }, new java.security.SecureRandom());
}
catch (NoSuchAlgorithmException e)
{
e.printStackTrace();
}
catch (KeyManagementException e)
{
e.printStackTrace();
}
return sslcontext;
}
private SSLContext getSSLContext()
{
if (this.sslcontext == null)
{
this.sslcontext = createSSLContext();
}
return this.sslcontext;
}
public Socket createSocket(Socket socket, String host, int port,
boolean autoClose) throws IOException, UnknownHostException
{
return getSSLContext().getSocketFactory().createSocket(socket, host,
port, autoClose);
}
public Socket createSocket(String host, int port) throws IOException,
UnknownHostException
{
return getSSLContext().getSocketFactory().createSocket(host, port);
}
public Socket createSocket(String host, int port, InetAddress clientHost,
int clientPort) throws IOException, UnknownHostException
{
return getSSLContext().getSocketFactory().createSocket(host, port,
clientHost, clientPort);
}
public Socket createSocket(String host, int port, InetAddress localAddress,
int localPort, HttpConnectionParams params) throws IOException,
UnknownHostException, ConnectTimeoutException
{
if (params == null)
{
throw new IllegalArgumentException("Parameters may not be null");
}
int timeout = params.getConnectionTimeout();
SocketFactory socketfactory = getSSLContext().getSocketFactory();
if (timeout == 0)
{
return socketfactory.createSocket(host, port, localAddress,
localPort);
}
else
{
Socket socket = socketfactory.createSocket();
SocketAddress localaddr = new InetSocketAddress(localAddress,
localPort);
SocketAddress remoteaddr = new InetSocketAddress(host, port);
socket.bind(localaddr);
socket.connect(remoteaddr, timeout);
return socket;
}
}
//
private static class TrustAnyTrustManager implements X509TrustManager
{
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException
{
}
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException
{
}
public X509Certificate[] getAcceptedIssuers()
{
return new X509Certificate[]
{};
}
}
}
次はhttpClientの実装クラスです.
package org.study.meteor.ticket.util;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.httpclient.protocol.Protocol;
/**
* HttpDoPostUtils.java Create on 2012-9-7 3:08:18
*
*
* Copyright (c) 2012 by MTA.
*
* @author lmeteor
* @Email [email protected]
* @description HTTP
* @version 1.0
*/
@SuppressWarnings("deprecation")
public class HttpDoPostUtils
{
private static HttpClient httpClient = null;
static
{
//
Protocol myhttps = new Protocol("https", new MySecureProtocolSocketFactory(), 443);
// https
Protocol.registerProtocol("https", myhttps);
httpClient = new HttpClient();
}
/**
* ,
* @param url
* URL
* @param pList
*
* @return
* @throws UnsupportedEncodingException
*/
public static String doRequestToString(String url,List<NameValuePair> pList) throws UnsupportedEncodingException
{
// postMethod
PostMethod pmethod = getPostMethod(url);
pmethod.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, "utf-8");
//
if(null != pList && pList.size() > 0)
{
pmethod.setRequestBody(pList.toArray(new NameValuePair[pList.size()]));
}
String value = "";
try
{
httpClient.executeMethod(pmethod);
value = pmethod.getResponseBodyAsString();
}
catch ( HttpException e )
{
e.printStackTrace();
}
catch ( IOException e )
{
e.printStackTrace();
}
return value;
}
/**
* 12306
* @param url
* URL
* @param filePath
* :e:\\login.jpg
* @return
*/
public static File doGetFile(String url,String filePath)
{
PostMethod pmethod = getPostMethod(url);
pmethod.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, "utf-8");
try
{
httpClient.executeMethod(pmethod);
//
InputStream in = pmethod.getResponseBodyAsStream();
//
BufferedInputStream bis = new BufferedInputStream(in);
File file = new File(filePath);
FileOutputStream fs = new FileOutputStream(file);
byte[] buf = new byte[1024];
int len = bis.read(buf);
if(len == -1 || len == 0){
file.delete();
file = null;
}
while (len != -1) {
fs.write(buf, 0, len);
len = bis.read(buf);
}
fs.flush();
fs.close();
return file;
}
catch (HttpException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
return null;
}
public static List<NameValuePair> createNameValuePair(String params) {
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
if (null != params && !params.trim().equals("")) {
String[] _params = params.split("&");
// userCookieList = new AttributeList();
for (int i = 0; i < _params.length; i++) {
int _i = _params[i].indexOf("=");
if (_i != -1) {
String name = _params[i].substring(0, _i);
String value = _params[i].substring(_i + 1);
nvps.add(new NameValuePair(name, value));
}
}
}
return nvps;
}
public static PostMethod getPostMethod(String url)
{
PostMethod pmethod = new PostMethod(url);
//
pmethod.addRequestHeader("Connection", "keep-alive");
pmethod.addRequestHeader("Cache-Control", "max-age=0");
pmethod.addRequestHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
pmethod.addRequestHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
return pmethod;
}
}
シミュレーションリクエストのクラスが出てきましたが、これからシミュレーションログインを行い、ログイン前に12306自身がどのようにリクエストをコミットし、どのパラメータがバックグラウンドに含まれているかを知る必要があります.firebugで簡単に見つけることができます.
12306ログイン前に「https://dynamic.12306.cn/otsweb/loginAction.do?method=loginAysnSuggest」が呼び出され、バックグラウンドには次のようなJSONメッセージが返されます.
{"loginRand":"652","randError":"Y"}
randErrorが「Y」の場合、フォームFORMがコミットされ、loginRandの値がフォーム内の非表示ドメインに初期化され、パラメータとしてバックグラウンドに渡されます.
最後のステップはパラメータの接合です.具体的な操作コードは次のとおりです.
package org.study.meteor.ticket.util;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import org.study.meteor.ticket.domain.LoginBeforeValidatior;
import net.sf.json.JSONObject;
/**
* Login.java.java Create on 2012-9-26 1:48:42
*
*
* Copyright (c) 2012 by MTA.
*
* @author lmeteor
* @Email [email protected]
* @description
* @version 1.0
*/
public class Login
{
/**
*
* @param filePath
* @return
*/
public static String getRandCode(String filePath)
{
String randCode = "";
/** */
HttpDoPostUtils.doGetFile(PropertiesUtils.newInstance().getPropertiesValue("loginCode"),filePath);
randCode = readString(" :");
return randCode;
}
/**
*
* @throws UnsupportedEncodingException
*/
public static void doLogin() throws UnsupportedEncodingException
{
String randCode = getRandCode("e:\\login.jpg");
/** */
String loginBeforeVal = HttpDoPostUtils.doRequestToString(PropertiesUtils.newInstance().getPropertiesValue("loginBeforeValidatiorUrl"),null);
// JSON
JSONObject jsonObj = JSONObject.fromObject(loginBeforeVal);
LoginBeforeValidatior loginBefore = new LoginBeforeValidatior();
loginBefore = (LoginBeforeValidatior) JSONObject.toBean(jsonObj, LoginBeforeValidatior.class);
//
StringBuffer params = new StringBuffer();
params.append("loginRand="+loginBefore.getLoginRand()).append("&")
.append("refundLogin=N").append("&")
.append("refundFlag=Y").append("&")
.append("loginUser.user_name="+PropertiesUtils.newInstance().getPropertiesValue("username")).append("&")
.append("nameErrorFocus=&")
.append("user.password="+PropertiesUtils.newInstance().getPropertiesValue("password")).append("&")
.append("passwordErrorFocus=&")
.append("randCode="+randCode).append("&")
.append("randErrorFocus=");
//
String loginResponseText = HttpDoPostUtils.doRequestToString(PropertiesUtils.newInstance().getPropertiesValue("loginUrl"),HttpDoPostUtils.createNameValuePair(params.toString()));
System.out.println(loginResponseText);
}
/**
*
* @param msg
* @return
* @throws Exception
*/
private static String readString(String msg)
{
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
try{
System.out.print(msg+": ");
return bufferedReader.readLine();
}catch(Exception e){
}
return "1245";
}
public static void main(String[] args) throws UnsupportedEncodingException
{
//Login login = new Login();
//login.doLogin();
Login.doLogin();
}
}
URLはすべてプロファイルの中にあり、大体以下の通りです.
#12306 URL
loginBeforeValidatiorUrl=https://dynamic.12306.cn/otsweb/loginAction.do?method=loginAysnSuggest
#12306
loginCode=https://dynamic.12306.cn/otsweb/passCodeAction.do?rand=sjrand
# URL
loginUrl=https://dynamic.12306.cn/otsweb/loginAction.do?method=login
#
username=xxxx
#
password=xxx
戻ってきたHTMLで、自分の名前を見たら、ログインに成功したということになります.みんながまた何かしたい動作があれば、みんなの想像力を発揮することができます.
勉強としてしか使いません!
変換元:http://www.cnblogs.com/lmeteor/archive/2012/09/27/2705458.html