- Uma solicitação GET vazia é enviada para o endereço http: // localhost: 8080 / login .
- 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".
- 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”.
- 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.
- 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.
- Implementação em Java, HttpURLConnection e CookieManager.
- Implementação Java, HttpURLConnection sem CookieManager.
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 humanosToda 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.