1

The only way I can get my code to programmatically login to any URL is by using CookieHandler.setDefault(new CookieManager);. Which is fine, but I want to understand how the cookie is being maintained between each new HttpsURLConnection.

Can someone please show how to make the code below log into a gmail account without having to use CookieHandler.setDefault(new CookieManager);? Thanks.

**NOTES:
- substitute with your own email and password.
-CookieHandler.setDefault(new CookieManager); is commented out in the code below.

public class GmailApp {

    private List<String> cookies;
    private HttpsURLConnection conn;

    public static void main(String[] args) throws Exception {

        String url = "https://accounts.google.com/ServiceLoginAuth";
        String gmail = "https://mail.google.com/mail/";

        GmailApp http = new GmailApp();

        // CookieHandler.setDefault(new CookieManager());

        String page = http.GetPageContent(url);
        String postParams = http.getFormParams(page, "myemail@gmail.com", "mypassword");
        http.sendPost(url, postParams);

        String result = http.GetPageContent(gmail);
        System.out.println(result);
    }

    private void sendPost(String url, String postParams) throws Exception {

        URL obj = new URL(url);
        conn = (HttpsURLConnection) obj.openConnection();
        conn.setDoOutput(true);
        DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
        wr.writeBytes(postParams);
        wr.flush();
        wr.close();

        int responseCode = conn.getResponseCode();
        System.out.println("\nSending 'POST' request to URL : " + url);
        System.out.println("Post parameters : " + postParams);
        System.out.println("Response Code : " + responseCode);

        BufferedReader in =
                new BufferedReader(new InputStreamReader(conn.getInputStream()));
        String inputLine;
        StringBuffer response = new StringBuffer();

        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);
        }
        in.close();
    }

    private String GetPageContent(String url) throws Exception {

        URL obj = new URL(url);
        conn = (HttpsURLConnection) obj.openConnection();
        conn.setRequestMethod("GET");
        conn.setUseCaches(false);
        if (cookies != null) {
            for (String cookie : this.cookies) {
                conn.addRequestProperty("Cookie", cookie.split(";", 1)[0]);
            }
        }
        int responseCode = conn.getResponseCode();
        System.out.println("\nSending 'GET' request to URL : " + url);
        System.out.println("Response Code : " + responseCode);

        BufferedReader in =
                new BufferedReader(new InputStreamReader(conn.getInputStream()));
        String inputLine;
        StringBuffer response = new StringBuffer();

        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);
        }
        in.close();
        setCookies(conn.getHeaderFields().get("Set-Cookie"));
        return response.toString();
    }

    public String getFormParams(String html, String username, String password)
            throws UnsupportedEncodingException {

        System.out.println("Extracting form's data...");

        Document doc = Jsoup.parse(html);

        Element loginform = doc.getElementById("gaia_loginform");
        Elements inputElements = loginform.getElementsByTag("input");
        List<String> paramList = new ArrayList<String>();
        for (Element inputElement : inputElements) {
            String key = inputElement.attr("name");
            String value = inputElement.attr("value");

            if (key.equals("Email"))
                value = username;
            else if (key.equals("Passwd"))
                value = password;
            paramList.add(key + "=" + URLEncoder.encode(value, "UTF-8"));
        }

        StringBuilder result = new StringBuilder();
        for (String param : paramList) {
            if (result.length() == 0) {
                result.append(param);
            } else {
                result.append("&" + param);
            }
        }
        return result.toString();
    }

    public void setCookies(List<String> cookies) {
        this.cookies = cookies;
    }

} 
dbconfession
  • 1,147
  • 2
  • 23
  • 36

1 Answers1

1

When you set a default CookieHandler statically via java.net.CookieHandler.setDefault(), current and future HttpURLConnections (via their underlying HTTP client classes) will check for the existence of this default cookie handler, and finding it will use it to retrieve cookies for requests, and store new cookies set/returned. This provides a static cookie-jar for as long as you want to maintain cookies across all requests. Be sure to set the desired CookiePolicy, or java.net.CookiePolicy.ACCEPT_ORIGINAL_SERVER is the default.

Note there's a few issues with your code:

cookie.split(";", 1)[0]

This split won't do anything, you want cookie.split(";", 2)[0] (1->2) if you want to truncate the string from the first semicolon onwards.

Also, you are only calling setCookies after your GET requests - you also need to capture the cookies in the response to the POST login.

javabrett
  • 7,020
  • 4
  • 51
  • 73
  • The code I posted is just a sample. I guess i should have simplified it. The mentions you made do not pertain to my actual question. I just want someone to post a manual interpretation of how CookieHandler and CookieManager manages cookies. – dbconfession Apr 28 '15 at 18:07
  • I added some details on `CookieHandler`. – javabrett Apr 28 '15 at 23:02
  • 1
    Thanks brett. I guess ultimately, I want to be able to login and maintain a cookie across connections without employing `CookieHandler` so that I can understand fundamentally what it is doing. No matter what I do, each connection seems to fail even if I store the response cookie to a variable and set the next request to use that cookie with `.setRequestProperty("Cookie", loginCookie)`. Can you show how to manually handle a response cookie and use it effectively in the next request? – dbconfession Apr 29 '15 at 21:11