Android: inicia sesión en el sitio web y conserva sesión / cookie mediante DefaultHttpClient
He estado a través de diferentes tutoriales y este sitio web, pero no pude encontrar una solución adecuada. Por otro lado, he visto aplicaciones de registro en sitios web y solicitar más información, así que estoy seguro de que hay una manera de conseguir este trabajo, pero tal vez mi enfoque es todo mal.
Esto es lo que estoy tratando de hacer: Quiero iniciar sesión en un sitio web que necesita la autenticación de usuario y luego leer y analizar sitios web que sólo son accesibles si el usuario está conectado. El problema: después de POSTing las credenciales al sitio web, recibo Una cookie que no parece estar preservada en mi HttpClient, aunque los documentos sugieren que exactamente eso debería suceder.
- Estrategia de la aplicación de Android para realizar un seguimiento de una sesión de inicio de sesión
- Mantener sesión de cookie en Android
- Hacer un login con facebook usando Facebook SDK 3.0
- Reemplazo de código de Facebook obsoleto para Android
- Cómo hacer la reanudación de sesión SSL en Android
He aquí algunos de mi código:
DefaultHttpClient httpclient = new DefaultHttpClient(); HttpPost httpost = new HttpPost(LOGIN_URL); List<NameValuePair> nvps = new ArrayList<NameValuePair>(); nvps.add(new BasicNameValuePair(USER_FIELD, login)); nvps.add(new BasicNameValuePair(PASS_FIELD, pw)); nvps.add(new BasicNameValuePair(REMEMBERME, "on")); httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8)); HttpResponse response = httpclient.execute(httpost); HttpEntity entity = response.getEntity(); if (entity != null) { entity.consumeContent(); } List<Cookie> cookies = httpclient.getCookieStore().getCookies();
Cuando publico el contenido de "cookies", todo parece estar bien (recibo una sesión):
- [version: 0][name: ASP.NET_SessionId][value: xxx][domain: xxx][path: /][expiry: null]
Como he entendido, la cookie / sesión se conservará y se utilizará en mi HttpClient siempre y cuando no cerrarlo.
Al leer la siguiente página (que está restringida), usando este código:
HttpGet httpget2 = new HttpGet(RESTRICTED_URL); response = httpclient.execute(httpget2); entity = response.getEntity(); InputStream data = entity.getContent(); // data will be parsed here if (entity != null) { entity.consumeContent(); } // connection will be closed afterwards
Si publico la respuesta de la solicitud GET (usando response.getStatusLine()
) obtengo un mensaje "200 OK", pero al analizar el sitio que se devuelve se muestra que el login se ha perdido (sólo recupero un formulario de inicio de sesión).
Cualquier ayuda es apreciada.
- Uso de cookies con solicitudes de Retrofit Robospice
- ¿Cómo puedo administrar la sesión en el inicio / cierre de sesión de Android?
- ¿Cómo puedo salir con AndroidAccountManager?
- Patrón de diseño de inicio de sesión de aplicaciones de Android
- Mantenga la sesión entre loadUrl de Android WebView
- Inicio de sesión de Android - autenticador de cuentas vs autenticación manual
- ¿La forma preferida de conectar AudioEffect a la mezcla global?
- Permiso de denegación: proveedor de apertura com.android.providers.contacts.ContactsProvider2
En una aplicación a la que tengo que iniciar sesión. Primero tengo que ejecutar un GET seguido de un POST y luego el GET de nuevo. El First get instanciará un ID de Jsession para mi conexión. El POST autenticará mi ID y luego el original obtendrá GET devolverá el contenido real.
El código siguiente es para una aplicación que se ejecuta en JBoss
public boolean login() { HttpGet httpGet = new HttpGet( "http://localhost:8080/gwt-console-server/rs/identity/secure/sid/"); HttpPost httpPost = new HttpPost("http://localhost:8080/gwt-console-server/rs/identity/secure/j_security_check"); HttpResponse response = null; List<NameValuePair> nvps = new ArrayList<NameValuePair>(); nvps.add(new BasicNameValuePair(USER_FIELD, userName)); nvps.add(new BasicNameValuePair(PASS_FIELD, password)); try { httpPost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8)); response = httpClient.execute(httpGet); EntityUtils.consume(response.getEntity()); response = httpClient.execute(httpPost); EntityUtils.consume(response.getEntity()); response = httpClient.execute(httpGet); String sessionId =EntityUtils.toString(response.getEntity()); String cookieId =""; List<Cookie> cookies = ((AbstractHttpClient) httpClient).getCookieStore().getCookies(); for (Cookie cookie: cookies){ if (cookie.getName().equals("JSESSIONID")){ cookieId = cookie.getValue(); } } if(sessionId!= null && sessionId.equals(cookieId) ){ return true; } } catch (ClientProtocolException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return false; }
Asumiendo que el objeto httpclient
es el mismo en ambos casos, y suponiendo que RESTRICTED_URL
está en el mismo dominio que LOGIN_URL
, entonces creo que lo que tienes debería funcionar.
Es posible que desee utilizar Wireshark o un proxy o algo parecido para examinar las solicitudes HTTP que está realizando, para ver si la cookie está realmente conectada a la solicitud. Puede ser que la cookie está siendo adjunta, en cuyo caso hay algo más que está haciendo que la segunda solicitud de fallar.
Usted tiene que hacer DefaultHttpClient httpclient
con patrón singleton para sessioncookie que todavía tiene sesión de sesión de inicio de sesión.
Esta es la clase Mainactivity
:
public static DefaultHttpClient httpClient; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); RequestPage request = new RequestPage(); request.post("http://www.example.com/login.php"); RequestPage requestProfile =new RequestPage(); requestProfile.post("http://www.example.com/profile.php"); }
Y esta es la clase RequestPage
:
private InputStream post(String url){ String paramUsername = "username"; String paramPassword = "pass"; if(MainActivity.httpClient==null){ MainActivity.httpClient = new DefaultHttpClient(); } DefaultHttpClient httpClient = MainActivity.httpClient; // In a POST request, we don't pass the values in the URL. //Therefore we use only the web page URL as the parameter of the HttpPost argument HttpPost httpPost = new HttpPost(url); // Because we are not passing values over the URL, we should have a mechanism to pass the values that can be //uniquely separate by the other end. //To achieve that we use BasicNameValuePair //Things we need to pass with the POST request BasicNameValuePair usernameBasicNameValuePair = new BasicNameValuePair("username", paramUsername); BasicNameValuePair passwordBasicNameValuePAir = new BasicNameValuePair("password", paramPassword); // We add the content that we want to pass with the POST request to as name-value pairs //Now we put those sending details to an ArrayList with type safe of NameValuePair List<NameValuePair> nameValuePairList = new ArrayList<NameValuePair>(); nameValuePairList.add(usernameBasicNameValuePair); nameValuePairList.add(passwordBasicNameValuePAir); try { // UrlEncodedFormEntity is an entity composed of a list of url-encoded pairs. //This is typically useful while sending an HTTP POST request. UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(nameValuePairList); // setEntity() hands the entity (here it is urlEncodedFormEntity) to the request. httpPost.setEntity(urlEncodedFormEntity); try { // HttpResponse is an interface just like HttpPost. //Therefore we can't initialize them HttpResponse httpResponse = httpClient.execute(httpPost); // According to the JAVA API, InputStream constructor do nothing. //So we can't initialize InputStream although it is not an interface return httpResponse.getEntity().getContent(); } catch (ClientProtocolException cpe) { System.out.println("First Exception caz of HttpResponese :" + cpe); cpe.printStackTrace(); } catch (IOException ioe) { System.out.println("Second Exception caz of HttpResponse :" + ioe); ioe.printStackTrace(); } } catch (UnsupportedEncodingException uee) { System.out.println("An Exception given because of UrlEncodedFormEntity argument :" + uee); uee.printStackTrace(); } return null; }
Usted puede hacerlo de esta manera, aunque es más bien una solución.
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); WebView webv = (WebView)findViewById(R.id.MainActivity_webview); webv.setWebViewClient(new WebViewClient(){ @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { view.loadUrl(url); return true; } }); String postData = FIELD_NAME_LOGIN + "=" + LOGIN + "&" + FIELD_NAME_PASSWD + "=" + PASSWD; // this line logs you in and you stay logged in // I suppose it works this way because in this case WebView handles cookies itself webv.postUrl(URL, EncodingUtils.getBytes(postData, "utf-8")); }
- Fragmentos restauran el estado en la orientación cambiada
- Android: las esquinas de forma no funcionan al configurar las esquinas individuales