回:HttpClient模擬登録12306チケット購入サイト


まず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);
具体的なコードは以下の通りです.
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