Autenticação via Socket (protocolo HTTP)

[quote]Ele pede para chamar o método setDoOutput(true).
Quando chamo este método antes de criar o OutputStreamWriter, ele dá outra exceção:
[/quote]

Amigo… realmente ta estranho…
Eu aqui fiz alguns testes basicos (criei uma página besta de login e funcionou).
Ai comecei a tentar em outros lugares… tive alguns problemas e acrescentei header para funcionar.

		con.setRequestMethod("POST");

		con.setRequestProperty("Host", "www.host.com.br");
		con.setRequestProperty("Accept", "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-powerpoint, application/vnd.ms-excel, application/msword, */*");
		con.setRequestProperty("Accept-Language", "en-us");
		con.setRequestProperty("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7");
		con.setRequestProperty("Keep-Alive", "300");
		con.setRequestProperty("Accept-Encoding", "gzip, deflate");
		con.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461)");
		con.setRequestProperty("Connection", "Keep-Alive");
		con.setRequestProperty("Cache-Control", "no-cache");
		con.setRequestProperty("Referer", "http://www.host.com.br/");

		con.setRequestProperty("Content-Type", 
	           "application/x-www-form-urlencoded");
				
		con.setRequestProperty("Content-Length", "" + 
	               Integer.toString(data.getBytes().length));
		con.setRequestProperty("Content-Language", "en-US");  
				
		
		con.setUseCaches (false);
		con.setDoInput(true);
		con.setDoOutput(true);	      

Mesmo assim… tiveram alguns casos que tive erro e não funcionou…
Ai comecei a testar em C e funcionava normalmente e em Java nada de funcionar…

então comecei a ver os pacotes com o Fiddler e Wireshark no linux… E vi que o Java estava adotando alguns comportamentos automáticamente e redirecionamento.

Pesquisei no google e falava para usar o método setFollowRedirects mas mesmo assim não tive sucesso…

Sempre que precisei fazer este tipo de coisa foi em C e em C tudo que tentava funcionava, então tive certeza que não é problema de comunicação… é algo especifico que precisa definir no Java mesmo…

Recomendo fortemente seguir o conselho do amigo luistiagos e tentar usar o HttpClient… Pois pode ser alguma coisa especifica do HttpUrlConnection…

Quando conseguir fazer rodar posta para agente… se eu tiver esta necessidade e não conseguir fazer em Java, farei novamente em C… embora em varios casos acrescentar os headers funcionou…

Abs

Amigo… esses problemas me deixam inquieto… (rsrsrs)
Bem… consegui fazer aqui funcionar… POST… url com http e https, tudo rolou…
o problema era mesmo de redirecionamento, precisa fazer um: con.setInstanceFollowRedirects(false); em alguns casos…
Sendo assim consegui autenticar, ver depois o cookie e pegar páginas que precisam de autenticação em HTTP e HTTPS.

Resolvi então implementar o robozinho que tinha feito em C pro VOL em Java…

Segue o código do mesmo… para gerenciar o cookie utilizei a classe CookieManager que peguei na internet no link acima…

Agora é vc tentar ver o que ocorre ai com o Fiddler, Wireshark ou outro sniffer e tentar ver como fazer pra sua URL especifica funcionar…

Abs

ConexaoTeste.java

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.Authenticator;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.PasswordAuthentication;
import java.net.Proxy;
import java.net.Proxy.Type;
import java.net.SocketAddress;
import java.net.URL;
import java.net.URLEncoder;

import javax.net.ssl.HttpsURLConnection;

public class ConexaoTeste {
	
	public static void main(String[] args) {
		try {
			
			ConexaoTeste volTeste = new ConexaoTeste(true);
			volTeste.exibirRanking();
			
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	private String domain = "dominio"; 
	private String userName = "usuario";
	private String password = "senha";	
	private boolean proxy = false;
	
	public ConexaoTeste(boolean proxy) {
		this.proxy = proxy;
	}
	
	public void exibirRanking() throws MalformedURLException, UnsupportedEncodingException, IOException {
		
		Authenticator.setDefault(new Authenticator() {
	        @Override
	        public PasswordAuthentication getPasswordAuthentication() {
	            return new PasswordAuthentication(domain + "\\" + userName, password.toCharArray());
	        }
	    });
		
		CookieManager cm = new CookieManager();
		
		// Primeiro, pegar o cookie
		obterCookie(cm);
		System.out.println("Cookie: " + cm.toString());
		
		// Segundo, autenticar
		if (autenticar("usuario", "senha", cm)) {
			System.out.println("Autenticou");	
			
			// Terceiro, ver o ranking
			String ranking = capturarRanking(cm);
			System.out.println("Ranking: " + ranking);
			
		} else {
			System.out.println("Não Autenticou");
		}
		
	}
	
	private void obterCookie(CookieManager cm) 
			throws MalformedURLException, IOException {
		String urlCookie = "http://www.vivaolinux.com.br/index.php";
		HttpURLConnection con = abrirConexao(urlCookie, false);
		cm.storeCookies(con);
		con.disconnect();
	}
	
	private boolean autenticar(String usuario, String senha, CookieManager cm) 
			throws UnsupportedEncodingException, IOException {
		
		boolean autenticado = false;
		
		String data = URLEncoder.encode("referer", "UTF-8") + "=" + URLEncoder.encode("/index.php?", "UTF-8")
				+ "&" + URLEncoder.encode("formLogin", "UTF-8") + "=" + URLEncoder.encode(usuario, "UTF-8")
	    		+ "&" + URLEncoder.encode("formSenha", "UTF-8") + "=" + URLEncoder.encode(senha, "UTF-8")
	    		+ "&" + URLEncoder.encode("imageField2.x", "UTF-8") + "=" + URLEncoder.encode("0", "UTF-8")
	    		+ "&" + URLEncoder.encode("imageField2.y", "UTF-8") + "=" + URLEncoder.encode("0", "UTF-8")
	    		+ "&" + URLEncoder.encode("Submit", "UTF-8") + "=" + URLEncoder.encode("Entrar", "UTF-8");
	    
		String urlAutenticacao = "http://www.vivaolinux.com.br/testarLogin.php";
		HttpURLConnection con = abrirConexao(urlAutenticacao, false);

		// Não automatiza o redirecionamento de URLs
		con.setInstanceFollowRedirects(false);
		cm.setCookies(con);
		con.setRequestMethod("POST");

		// Headers
		con.setRequestProperty("Host", "www.vivaolinux.com.br");
		con.setRequestProperty("Accept", "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-powerpoint, application/vnd.ms-excel, application/msword, */*");
		con.setRequestProperty("Accept-Language", "en-us");
		con.setRequestProperty("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7");
		con.setRequestProperty("Keep-Alive", "300");
		con.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461)");
		con.setRequestProperty("Connection", "Keep-Alive");
		con.setRequestProperty("Cache-Control", "no-cache");
		con.setRequestProperty("Referer", "http://www.vivaolinux.com.br/index.php");

		con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
		con.setRequestProperty("Content-Length", "" + Integer.toString(data.getBytes().length));
		con.setRequestProperty("Content-Language", "en-US");  
		
		con.setUseCaches (false);
		con.setDoInput(true);
		con.setDoOutput(true);	      

		// Envia dados
	    DataOutputStream wr = new DataOutputStream (con.getOutputStream());
	    wr.writeBytes (data);
	    wr.flush();
	    wr.close();
		
	    // Leitura de resposta (se precisar)
	    BufferedReader rd = new BufferedReader(new InputStreamReader(con.getInputStream()));
	    String line;
	    StringBuilder sb = new StringBuilder("");
	    while ((line = rd.readLine()) != null) {
	    	sb.append(line);
	    }
	    rd.close();		
	    
	    // Vamos ver se autenticou (no caso o vol redireciona voltando um 302)
	    if (con.getResponseCode() == 302) {
	    	autenticado = true;
	    }
	    
	    return autenticado;
	}

	
	private String capturarRanking(CookieManager cm) throws UnsupportedEncodingException, IOException {
		String ranking = null;
		String urlRank = "http://www.vivaolinux.com.br/index.php";
		HttpURLConnection con = abrirConexao(urlRank, false);
		cm.setCookies(con);

		con.setUseCaches (false);
		con.setDoInput(true);
		con.setDoOutput(true);	      

		// Leitura do HTML, após autenticado com o mesmo cookie
		BufferedReader rd = new BufferedReader(new InputStreamReader(con.getInputStream()));
	    String line;
	    StringBuilder sb = new StringBuilder("");
	    while ((line = rd.readLine()) != null) {
	    	sb.append(line);
	    }
	    rd.close();
	    
	    // Tenta pegar o ranking
	    int posRank = sb.indexOf("Ranking: <b>");
	    int fimRank = sb.indexOf("</b>", posRank);
	    if (posRank > 0 && fimRank > 0) {
	    	ranking = sb.substring(posRank + 12, fimRank - 5);
	    }
	    
	    return ranking;
	    
	}
	
	private Proxy getProxy() {
		if (this.proxy) {
		   SocketAddress socketAddress = new InetSocketAddress("127.0.0.1", 3128);			
			return new Proxy(Type.HTTP, socketAddress);
		} else {
			return null;
		}
	}
	
	private HttpURLConnection abrirConexao(String enderecoPagina, boolean ssl) throws MalformedURLException, IOException {
		URL url = new URL(enderecoPagina);
		
		if (ssl) {			
			if (getProxy() != null) {
				HttpsURLConnection con = (HttpsURLConnection) url.openConnection(getProxy());
				return con;
			} else {
				HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
				return con;
			}
			
		} else {
			if (getProxy() != null) {
				HttpURLConnection con = (HttpURLConnection) url.openConnection(getProxy());
				return con;
			} else {
				HttpURLConnection con = (HttpURLConnection) url.openConnection();
				return con;
			}
		}
		
	}

}

CookieManager.java


import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.StringTokenizer;

    /**
     * CookieManager is a simple utilty for handling cookies when working
     * with java.net.URL and java.net.URLConnection
     * objects.
     * 
     * 
     *     Cookiemanager cm = new CookieManager();
     *     URL url = new URL("http://www.hccp.org/test/cookieTest.jsp");
     *     
     *      . . . 
     *
     *     // getting cookies:
     *     URLConnection conn = url.openConnection();
     *     conn.connect();
     *
     *     // setting cookies
     *     cm.storeCookies(conn);
     *     cm.setCookies(url.openConnection());
     * 
     *     @author Ian Brown
     *      
     **/

public class CookieManager {
        
    private Map store;

    private static final String SET_COOKIE = "Set-Cookie";
    private static final String COOKIE_VALUE_DELIMITER = ";";
    private static final String PATH = "path";
    private static final String EXPIRES = "expires";
    private static final String DATE_FORMAT = "EEE, dd-MMM-yyyy hh:mm:ss z";
    private static final String SET_COOKIE_SEPARATOR="; ";
    private static final String COOKIE = "Cookie";

    private static final char NAME_VALUE_SEPARATOR = '=';
    private static final char DOT = '.';
    
    private DateFormat dateFormat;

    public CookieManager() {

	store = new HashMap();
	dateFormat = new SimpleDateFormat(DATE_FORMAT);
    }
    

    /**
     * Retrieves and stores cookies returned by the host on the other side
     * of the the open java.net.URLConnection.
     *
     * The connection MUST have been opened using the connect()
     * method or a IOException will be thrown.
     *
     * @param conn a java.net.URLConnection - must be open, or IOException will be thrown
     * @throws java.io.IOException Thrown if conn is not open.
     */
    public void storeCookies(URLConnection conn) throws IOException {
	
	// let's determine the domain from where these cookies are being sent
	String domain = getDomainFromHost(conn.getURL().getHost());
	
	
	Map domainStore; // this is where we will store cookies for this domain
	
	// now let's check the store to see if we have an entry for this domain
	if (store.containsKey(domain)) {
	    // we do, so lets retrieve it from the store
	    domainStore = (Map)store.get(domain);
	} else {
	    // we don't, so let's create it and put it in the store
	    domainStore = new HashMap();
	    store.put(domain, domainStore);    
	}
	
	
	
	
	// OK, now we are ready to get the cookies out of the URLConnection
	
	String headerName=null;
	for (int i=1; (headerName = conn.getHeaderFieldKey(i)) != null; i++) {
	    if (headerName.equalsIgnoreCase(SET_COOKIE)) {
		Map cookie = new HashMap();
		StringTokenizer st = new StringTokenizer(conn.getHeaderField(i), COOKIE_VALUE_DELIMITER);
		
		// the specification dictates that the first name/value pair
		// in the string is the cookie name and value, so let's handle
		// them as a special case: 
		
		if (st.hasMoreTokens()) {
		    String token  = st.nextToken();
		    String name = token.substring(0, token.indexOf(NAME_VALUE_SEPARATOR));
		    String value = token.substring(token.indexOf(NAME_VALUE_SEPARATOR) + 1, token.length());
		    domainStore.put(name, cookie);
		    cookie.put(name, value);
		}
    
		while (st.hasMoreTokens()) {
		    String token  = st.nextToken();
		    cookie.put(token.substring(0, token.indexOf(NAME_VALUE_SEPARATOR)).toLowerCase(),
		     token.substring(token.indexOf(NAME_VALUE_SEPARATOR) + 1, token.length()));
		}
	    }
	}
    }
 

    /**
     * Prior to opening a URLConnection, calling this method will set all
     * unexpired cookies that match the path or subpaths for thi underlying URL
     *
     * The connection MUST NOT have been opened 
     * method or an IOException will be thrown.
     *
     * @param conn a java.net.URLConnection - must NOT be open, or IOException will be thrown
     * @throws java.io.IOException Thrown if conn has already been opened.
     */
    public void setCookies(URLConnection conn) throws IOException {
	
	// let's determine the domain and path to retrieve the appropriate cookies
	URL url = conn.getURL();
	String domain = getDomainFromHost(url.getHost());
	String path = url.getPath();
	
	Map domainStore = (Map)store.get(domain);
	if (domainStore == null) return;
	StringBuffer cookieStringBuffer = new StringBuffer();
	
	Iterator cookieNames = domainStore.keySet().iterator();
	while(cookieNames.hasNext()) {
	    String cookieName = (String)cookieNames.next();
	    Map cookie = (Map)domainStore.get(cookieName);
	    // check cookie to ensure path matches  and cookie is not expired
	    // if all is cool, add cookie to header string 
	    if (comparePaths((String)cookie.get(PATH), path) && isNotExpired((String)cookie.get(EXPIRES))) {
		cookieStringBuffer.append(cookieName);
		cookieStringBuffer.append("=");
		cookieStringBuffer.append((String)cookie.get(cookieName));
		if (cookieNames.hasNext()) cookieStringBuffer.append(SET_COOKIE_SEPARATOR);
	    }
	}
	try {
	    conn.setRequestProperty(COOKIE, cookieStringBuffer.toString());
	} catch (java.lang.IllegalStateException ise) {
	    IOException ioe = new IOException("Illegal State! Cookies cannot be set on a URLConnection that is already connected. " 
	    + "Only call setCookies(java.net.URLConnection) AFTER calling java.net.URLConnection.connect().");
	    throw ioe;
	}
    }

    private String getDomainFromHost(String host) {
	if (host.indexOf(DOT) != host.lastIndexOf(DOT)) {
	    return host.substring(host.indexOf(DOT) + 1);
	} else {
	    return host;
	}
    }

    private boolean isNotExpired(String cookieExpires) {
	if (cookieExpires == null) return true;
	Date now = new Date();
	try {
	    return (now.compareTo(dateFormat.parse(cookieExpires))) <= 0;
	} catch (java.text.ParseException pe) {
	    pe.printStackTrace();
	    return false;
	}
    }

    private boolean comparePaths(String cookiePath, String targetPath) {
	if (cookiePath == null) {
	    return true;
	} else if (cookiePath.equals("/")) {
	    return true;
	} else if (targetPath.regionMatches(0, cookiePath, 0, cookiePath.length())) {
	    return true;
	} else {
	    return false;
	}
	
    }
    
    /**
     * Returns a string representation of stored cookies organized by domain.
     */

    public String toString() {
	return store.toString();
    }
    
    public static void main(String[] args) { 
	CookieManager cm = new CookieManager();
	try {
	    URL url = new URL("http://www.hccp.org/test/cookieTest.jsp");
	    URLConnection conn = url.openConnection();
	    conn.connect();
	    cm.storeCookies(conn);
	    System.out.println(cm);
	    cm.setCookies(url.openConnection());
	} catch (IOException ioe) {
	    ioe.printStackTrace();
	}
    }
    
}