Conexión a sesión en Java y Python. HttpURLConnection y CookieManager (Java). Solicitudes (Python)

Digamos que necesitamos conectarnos a un servidor, iniciar sesión y mantener una sesión. En el navegador se ve así:



  1. Se envía una solicitud GET vacía a la dirección http: // localhost: 8080 / login .
  2. El servidor envía un formulario para completar el nombre de usuario y la contraseña, y también envía una cookie del formulario "JSESSIONID = 094BC0A489335CF8EE58C8E7846FE49B".
  3. Después de completar el nombre de usuario y la contraseña, se envía una solicitud POST al servidor con la cookie recibida anteriormente, con la línea en la secuencia de salida "username = Fox & password = 123". Los encabezados además especifican "Content-Type: application / x-www-form-urlencoded".
  4. En respuesta, el servidor nos envía una nueva cookie con un nuevo "JSESSIONID =". Inmediatamente redirige a http: // localhost: 8080 / por solicitud GET con una nueva cookie.
  5. Luego, puede usar con seguridad el resto de la API del servidor, pasando la última cookie en cada solicitud.


Veamos cómo se puede implementar esto en Java y Python.







Contenido





Implementación de Python. Peticiones



Al elegir una biblioteca de red Python , la mayoría de los sitios recomendarán la biblioteca de solicitudes , que cumple con su lema:

HTTP para humanos
Toda la tarea se resuelve con el siguiente script:



import requests
session = requests.session()  # 
url = "http://localhost:8080/login"
session.get(url)   # cookie
data = {"username": "Fox", "password": "123"} 
response = session.post(url, data=data) #


Tenga en cuenta que la manipulación de cookies y redireccionamiento ocurre bajo el capó, al igual que en un navegador. También se puede observar que si obtiene otra sesión variable2 , puede mantener activas dos conexiones a la vez.



Implementación de Java, HttpURLConnection y CookieManager



Encontrar una biblioteca para trabajar con una red Java conduce a varias bibliotecas a la vez.



Por ejemplo, java.net , Apache HttpClient y OkHttp3 .



Me decidí por HttpURLConnection (java.net). Las ventajas de esta biblioteca es que es un fuera de la caja de la biblioteca , y también, si es necesario escribir una aplicación para android, existe documentación en el sitio oficial . La desventaja es la gran cantidad de código. (Después de Python, es solo un dolor).



Vamos a empezar. De acuerdo con la documentación, puede usar el CookieManager para trabajar con sesiones :



CookieManager cookieManager = new CookieManager(null, CookiePolicy.ACCEPT_ALL);
CookieHandler.setDefault(cookieManager);


Cosas a tener en cuenta utilizando este enfoque:



  • "CookiePolicy.ACCEPT_ALL" indica que funciona con todas las cookies.
  • La variable cookieManager no se usará en ningún otro lugar. Controla todas las conexiones, y si es necesario mantener varias sesiones activas, será necesario cambiar manualmente la Cookie en esta variable.


Dado esto, puedes escribir en una línea:



 CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL));


Puntos 1 y 2. Ejecutemos una solicitud GET para obtener la primera cookie:



URL url = new URL("http://localhost:8080/login");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
final StringBuilder content = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
    content.append(inputLine);
}


Después de eso, nuestro cookieManager contendrá la cookie del servidor y la sustituirá automáticamente en la próxima solicitud.



La diversión comienza con una solicitud POST.



url = new URL("http://localhost:8080/login");
con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("POST");


Debe escribir en Encabezados "Tipo de contenido: aplicación / x-www-form-urlencoded".



Por qué el método se llama setRequestProperty, y no setHeaders (o addHeaders) con el método getHeaderField, sigue siendo un misterio.



con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");


Luego viene el código, que, por alguna razón, no está escondido debajo del capó de la biblioteca.



con.setDoOutput(true);


Necesitamos esta línea de código para abrir la transmisión saliente. Es curioso que sin esta línea recibamos el siguiente mensaje:



Excepción en el hilo "main" java.net.ProtocolException: no se puede escribir en una URLConnection si doOutput = false - llame a setDoOutput (true)

Abra la transmisión saliente y escriba el nombre de usuario y la contraseña allí:



final DataOutputStream out = new DataOutputStream(con.getOutputStream());
out.writeBytes("username=Fox&password=123");
out.flush();
out.close();


Queda por leer la respuesta de una solicitud ya redirigida.



Implementación de Java, HttpURLConnection sin CookieManager



Puede implementarlo sin un CookieManager y controlar el movimiento de la cookie usted mismo.

Punto 1 y 2. Sacamos la galleta.



URL url = new URL("http://localhost:8080/login");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
final StringBuilder content = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
    content.append(inputLine);
String cookie = con.getHeaderField("Set-Cookie").split(";")[0];
}


A continuación, enviamos una solicitud POST, solo que esta vez insertando una cookie y deshabilitando la redirección automática, ya que antes de eso, debe tener tiempo para extraer una nueva cookie:



//  
url = new URL("http://localhost:8080/login");
con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("POST");
// headers  cookie
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
con.setRequestProperty("Cookie", cookie);
// 
con.setInstanceFollowRedirects(false);
//   
con.setDoOutput(true);
final DataOutputStream out = new DataOutputStream(con.getOutputStream());
out.writeBytes("username=Fox&password=123");
out.flush();
out.close();
//    cookie
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
final StringBuilder content = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
    content.append(inputLine);
String cookie2 = con.getHeaderField("Set-Cookie").split(";")[0];


A continuación, simplemente agregamos la siguiente línea a todas las solicitudes:



con.setRequestProperty("Cookie", cookie2);


Espero que haya sido útil. Los comentarios dan la bienvenida a opciones más simples.



All Articles