0

https プロトコルを使用する外部 Web サイトのコンテンツにアクセスする必要があります。この Web サイトにはクラスのスケジュールが表示されます。この情報を解析してアプリに適用したいと考えています。

さて、httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs)); を使用して、ログイン ページに接続することを考えていました。ユーザー名とパスワードを入れた場所。次に、ログインする必要があるため、スケジュール ページに別の接続を作成します。しかし、2 番目の応答はログイン ページからの html を示しているため、この方法では機能しないと思います。アクセスできるようにするには、2 番目の要求を通過する必要があります。

私が使用しているコードは次のとおりです。

public class ConexionIntranet extends AsyncTask<String, Void, String>  {
private String sUserName = "username...";
private String sPassword = "password...";

protected String doInBackground(String... urls) {
    try {
        InputStream is = null;
        HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;

        DefaultHttpClient client = new DefaultHttpClient();

        SchemeRegistry registry = new SchemeRegistry();
        SSLSocketFactory socketFactory = SSLSocketFactory.getSocketFactory();
        socketFactory.setHostnameVerifier((X509HostnameVerifier) hostnameVerifier);
        registry.register(new Scheme("https", socketFactory, 443));
        SingleClientConnManager mgr = new SingleClientConnManager(client.getParams(), registry);
        DefaultHttpClient httpClient = new DefaultHttpClient(mgr, client.getParams());

        // Set verifier      
        HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);

        // Example send http request
        final String url = urls[0];
        HttpPost httpPost = new HttpPost(url);
        HttpPost httpPost2 = new HttpPost("https://url...");
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
        nameValuePairs.add(new BasicNameValuePair("user", sUserName));
        nameValuePairs.add(new BasicNameValuePair("pass", sPassword));
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
            httpPost2.setEntity(new UrlEncodedFormEntity(nameValuePairs));

        } catch (UnsupportedEncodingException e1) {
            Log.d("datos", "Error: "+e1.getMessage());
        }
        HttpResponse res;
        String result;
        try {
            res = httpClient.execute(httpPost);
            Log.d("datos", "Respuesta post: "+res.toString());

            res = httpClient.execute(httpPost2);
            is=res.getEntity().getContent();

            BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
            StringBuilder sb = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null) {
                sb.append(line + "\n");
            }
            is.close();
            result=sb.toString();
            Log.d("datos", "Respuesta: "+result);
        } catch (ClientProtocolException e) {
            Log.d("datos", "Error: "+e.getMessage());
        } catch (IOException e) {
            Log.d("datos", "Error: "+e.getMessage());
        }           
        return null;
    } catch (Exception e) {
        Log.d("datos", "Error: "+e.getMessage());
        return null;
    }
}}

これを解決する方法について何か考えはありますか? 1 回のリクエストで、コンテンツへのアクセスとログインを同時に行うことは可能でしょうか?

お時間をいただきありがとうございます!

乾杯。

4

2 に答える 2

1

HttpContextを使用して、後続のhttp呼び出しで再利用する必要があります。コンテキストはCookieをCookieストアに保存し(CookieStoreについてはjavadocを参照)、次の呼び出しで使用できるようにします。

まず、HttpContextを定義します。

DefaultHttpClient client = new DefaultHttpClient();
CookieStore cookieStore = new BasicCookieStore();
HttpContext httpContext = new BasicHttpContext();
httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);

次に、通話時に使用します。

    HttpResponse res;
    String result;
    try {
        res = httpClient.execute(httpPost, httpContext);
        Log.d("datos", "Respuesta post: "+res.toString());

        res = httpClient.execute(httpPost2, httpContext);
        is=res.getEntity().getContent();

        /* rest of the code */

    } catch (ClientProtocolException e) {
        Log.d("datos", "Error: "+e.getMessage());
    } catch (IOException e) {
        Log.d("datos", "Error: "+e.getMessage());
    }
于 2012-12-05T13:52:58.687 に答える
1

さて、私は最終的にHttpsURLConnectionを使用して正しい解決策を得ました。HttpClientは非推奨のようです:

ここにコードを残しておきます。同じ問題を抱えている人に役立つかもしれません。

public class ConexionIntranet extends AsyncTask<String, Void, String>  {
    private String sUserName = "user";
    private String sPassword = "password";
    private String urlLogin = "https://web.com/login";
    private String urlSchedule = "https://web.com/service";
    private String urlHost = "https://web.com/";
    private String resultado = "";

    protected String doInBackground(String... urls) {
        try {
            // Recuperamos los parámetros relativos a las urls así como user y pass introducidos por el usuario
            for(int i=0; i<urls.length; i++){
                if(i==0) urlLogin = urls[i];
                if(i==1) urlSchedule = urls[i];
                if(i==2) sUserName = urls[i];
                if(i==3) sPassword = urls[i];
                if(i==4) urlHost = urls[i];
            }
            HttpsURLConnection urlc = null;  
            DataOutputStream dataout = null;
            BufferedReader in = null;

            // Generamos el primer request, de tipo GET a la web de la intranet
            // En esta petición definimos que no siga redirecciones. Esto es debido a que al no tener cookie
            // la conexión lo toma como si no aceptara cookies y entrará en un bucle de dirección
            // saltando una excepción por exceder el número de redirecciones.
            // De esta forma, guardamos la cookie que nos asigna el response header y es la que emplearemos
            // en las sucesivas peticiones.
            URL urlPreLog = new URL(urlHost);
            HttpsURLConnection.setFollowRedirects(false);
            urlc = (HttpsURLConnection) urlPreLog.openConnection();
            // DoOutput a false para indicar que no es tipo POST
            urlc.setDoOutput(false);
            urlc.setRequestMethod("GET");
            // Imprimimos el código de respuesta recibido
            Log.d("datos", "Codigo respuesta: "+urlc.getResponseCode());
            // Obtenemos la cookie que nos han asignado.
            Map<String, List<String>> mapa = urlc.getHeaderFields();
            String newCookie = "";
            if(mapa!=null){
                Log.d("datos", "Recupera el mapa");
                List<String> list = mapa.get("Set-Cookie");         
                if((list != null)&&(list.size()>0)){
                    Log.d("datos", "Recupera la lista");
                    newCookie = list.get(0).substring(0,list.get(0).indexOf("path")).trim();
                }
            } 
            Log.d("datos", "Cookie: "+newCookie);
            //Desconectamos
            urlc.disconnect();




            // Generamos un segundo request, de tipo POST, a la página de login de la intranet.
            // Es aquí donde realizamos el login, por medio de los datos de output que se envían a la conexión
            // https establecida.
            // La cookie empleada es la recuperada anteriormente.
            URL urlLog = new URL(urlLogin);
            // Volvemos a habilitar la redirección
            HttpsURLConnection.setFollowRedirects(true);
            urlc = (HttpsURLConnection) urlLog.openConnection();
            urlc.setRequestMethod("POST");
            urlc.setDoOutput(true);
            urlc.setDoInput(true);
            urlc.setUseCaches(false);
            urlc.setAllowUserInteraction(false);
            urlc.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
            urlc.setRequestProperty("Cookie",newCookie);
            urlc.setRequestProperty("User-Agent", "Chrome");
            // Escribimos los datos de output que llevan entre otros el usuario y la contraseña
            String output = "accion="+URLEncoder.encode("validar", HTTP.UTF_8)+"&user="+URLEncoder.encode(sUserName, HTTP.UTF_8)
                    +"&pass="+ URLEncoder.encode(sPassword, HTTP.UTF_8)+"&conectar="+URLEncoder.encode("Conectar", HTTP.UTF_8);
            dataout = new DataOutputStream(urlc.getOutputStream());
            // Al hacer el writeBytes se produce la operación POST
            dataout.writeBytes(output);
            // Imprimimos el código de respuesta obtenido
            Log.d("datos", "Codigo respuesta: "+urlc.getResponseCode());
            // Desconectamos
            urlc.disconnect();




            // Generamos la última petición, de tipo GET a la página del horario de la intranet.
            URL urlSche = new URL(urlSchedule);
            urlc = (HttpsURLConnection) urlSche.openConnection();
            urlc.setRequestMethod("GET");
            urlc.setDoInput(true);
            urlc.setUseCaches(false);
            urlc.setAllowUserInteraction(false);
            urlc.setRequestProperty("Cookie", newCookie);
            urlc.setRequestProperty("User-Agent", "Chrome");
            in = new BufferedReader(new InputStreamReader(urlc.getInputStream(), Charset.forName("ISO-8859-15")),8096);
            // Imprimimos el código de respuesta obtenido
            Log.d("datos", "Codigo respuesta: "+urlc.getResponseCode());
            String response;
            StringBuilder sb = new StringBuilder();
            // Se guarda el código html de la respuesta
            while ((response = in.readLine()) != null) {
                sb.append(response + "\n");
                Log.d("datos", response); 
            }
            resultado = sb.toString();
            //Desconectamos y cerramos el stream de entrada
            urlc.disconnect();
            in.close();
        } catch (ProtocolException e) {
            Log.d("datos", "Error de protocolo: "+e.getMessage());
        } catch (IOException e) {
            Log.d("datos", "Error de E/S: "+e.getMessage());
        } catch (Exception e){
            Log.d("datos", "Excepcion: "+e.getMessage());
        }
        return resultado;
    }
}
于 2012-12-06T18:19:54.150 に答える