- Se envía una solicitud GET vacía a la dirección http: // localhost: 8080 / login .
- 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".
- 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".
- 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.
- 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.
- Implementación de Java, HttpURLConnection y CookieManager.
- Implementación de Java, HttpURLConnection sin CookieManager.
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 humanosToda 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.