Conectando-se à sessão em Java e Python. HttpURLConnection e CookieManager (Java). Solicitações (Python)

Digamos que precisamos nos conectar a um servidor, fazer login e manter uma sessão. Em um navegador, fica assim:



  1. Uma solicitação GET vazia é enviada para o endereço http: // localhost: 8080 / login .
  2. O servidor envia um formulário para preencher o nome de usuário e a senha e também envia um cookie no formato "JSESSIONID = 094BC0A489335CF8EE58C8E7846FE49B".
  3. Preenchendo o nome de usuário e a senha, uma solicitação POST é enviada ao servidor com o cookie recebido anteriormente, com uma linha no fluxo de saída "nome de usuário = Fox & senha = 123". Cabeçalhos também afirmam “Tipo de Conteúdo: application / x-www-form-urlencoded”.
  4. Em resposta, o servidor nos envia um novo cookie com um novo "JSESSIONID =". Ele é redirecionado imediatamente para http: // localhost: 8080 / por uma solicitação GET com um novo cookie.
  5. Além disso, você pode usar com segurança o restante da API do servidor, passando o último cookie em cada solicitação.


Vamos ver como isso pode ser implementado em Java e Python.







Conteúdo





Implementação em Python. solicitações de



Ao escolher uma biblioteca de rede Python , a maioria dos sites recomenda a biblioteca de solicitações , que cumpre seu lema:

HTTP para seres humanos
Toda a tarefa é resolvida pelo seguinte 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) #


Observe que a fraude e o redirecionamento de cookies ocorrem ocultamente, como em um navegador. Também é possível observar que, se você criar outra variável session2 , poderá manter duas conexões ativas ao mesmo tempo.



Implementação Java, HttpURLConnection e CookieManager



Encontrar uma biblioteca para trabalhar com uma rede Java leva a várias bibliotecas ao mesmo tempo.



Por exemplo, java.net , Apache HttpClient e OkHttp3 .



Eu decidi pelo HttpURLConnection (java.net). As vantagens desta biblioteca são que ela é "pronta para uso " e também, se você precisar escrever um aplicativo para Android, o site oficial possui documentação . A desvantagem é uma quantidade muito grande de código. (Depois do Python, é apenas uma dor.)



Então, vamos começar. De acordo com a documentação, você pode usar o CookieManager para trabalhar com sessões :



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


Pontos a serem observados usando essa abordagem:



  • "CookiePolicy.ACCEPT_ALL" indica para trabalhar com todos os cookies.
  • A variável cookieManager não será usada em nenhum outro lugar. Ele controla todas as conexões e, se for necessário manter várias sessões ativas, será necessário alterar manualmente o Cookie nessa variável.


Com isso em mente, você pode escrever em uma linha:



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


Pontos 1 e 2. Vamos executar uma solicitação GET para obter o primeiro 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);
}


Depois disso, nosso cookieManager conterá um cookie do servidor e o substituirá automaticamente na próxima solicitação.



A diversão começa com uma solicitação POST.



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


Você precisa escrever “Content-Type: application / x-www-form-urlencoded” nos cabeçalhos.



Por que o método é chamado setRequestProperty e não setHeaders (ou addHeaders) com o método getHeaderField é um mistério.



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


Em seguida, vem o código, que não é claro por quais razões eles não ficarão presos no capô da biblioteca.



con.setDoOutput(true);


Precisamos dessa linha de código para abrir o fluxo de saída. É engraçado que sem essa linha recebamos a seguinte mensagem:



Exceção no encadeamento "main" java.net.ProtocolException: não é possível gravar em um URLConnection se doOutput = false - chame setDoOutput (true)

Abra o fluxo de saída e escreva o nome de usuário e a senha lá:



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


Resta ler a resposta de uma solicitação já redirecionada.



Implementação Java, HttpURLConnection sem CookieManager



Você pode implementá-lo sem um CookieManager e controlar o movimento do cookie.

Parágrafos 1 e 2. Retiramos o 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);
String cookie = con.getHeaderField("Set-Cookie").split(";")[0];
}


Em seguida, enviamos uma solicitação POST, somente dessa vez inserindo um cookie e desativando o redirecionamento automático, pois antes disso, você precisa ter tempo para retirar um novo 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];


Em seguida, basta adicionar a seguinte linha a todas as solicitações:



con.setRequestProperty("Cookie", cookie2);


Espero que tenha sido útil. Opções mais simples são bem-vindas nos comentários.



All Articles