Programmatically logging in from WebView - java

In my Android application I'm using a web view to access some web mapping data provided by a server. The server requires some HTTP form based authentication to allow access to those data. Due to the fact that the site doesn't have a mobile version, displaying the login page (or any other pages) looks pretty bad . Unfortunately the site is hardly into my reach so I've thought of the following approach:
use a native user interface to collect the username and password
thought a Http post send those information to the server
after the response is received get the cookies the server is sending
set the cookies to the the web view
try to finally access the desired data
For now I'm just trying to pass the login phase.
Is this a viable solution , or is just plain wrong and I should try something else ?
For completeness I post the code below
A. The authentication part
private String authenticate() throws Exception
{
// Create a new HttpClient and Post Header
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://mySite/login_form");
HttpResponse response = null;
BufferedReader in = null;
String resultContent = null;
try
{
// Add data
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("came_from", ""));
nameValuePairs.add(new BasicNameValuePair("form.submitted", "1"));
nameValuePairs.add(new BasicNameValuePair("js_enabled", "0"));
nameValuePairs.add(new BasicNameValuePair("cookies_enabled", ""));
nameValuePairs.add(new BasicNameValuePair("login_name", ""));
nameValuePairs.add(new BasicNameValuePair("pwd_empty", "0"));
nameValuePairs.add(new BasicNameValuePair("name", "username"));
nameValuePairs.add(new BasicNameValuePair("password", "password"));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
// Create a local instance of cookie store
CookieStore cookieStore = new BasicCookieStore();
// Create local HTTP context
HttpContext localContext = new BasicHttpContext();
// Bind custom cookie store to the local context
localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
// Execute HTTP Post Request
response = httpclient.execute(httppost,localContext);
in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer sb = new StringBuffer("");
String line = "";
String NL = System.getProperty("line.separator");
while ((line = in.readLine()) != null)
{
sb.append(line + NL);
}
in.close();
resultContent = sb.toString();
Log.i("mytag","result :"+resultContent);
cookies = new java.util.ArrayList();
cookies = cookieStore.getCookies();
}
catch (ClientProtocolException e)
{
Log.i("mytag","Client protocol exception");
}
catch (IOException e)
{
Log.i("mytag","IOException");
}
catch(Exception e)
{
Log.i("mytag","Exception");
Log.i("mytag",e.toString());
}
return resultContent;
}
B. Setting the cookies and loading the desired page
private void init()
{
CookieSyncManager.createInstance(this);
CookieManager cookieMan= CookieManager.getInstance();
cookieMan.setAcceptCookie(true);
cookies = StartupActivity.listAfter;
if(cookies != null)
{
for (int i = 0; i<cookies.size(); i++)
{
Cookie cookie = cookies.get(i);
cookieMan.setCookie("cookie.getDomain()",cookie.getValue());
}
}
CookieSyncManager.getInstance().sync();
webView = (WebView)findViewById(R.id.web_view);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setBuiltInZoomControls(true);
webView.setWebViewClient(new HelloWebViewClient());
}
protected void onResume()
{
super.onResume();
// test if the we logged in
webView.loadUrl("mySite/myDesiredFeature");
}
The results of loading that page is that the login_page form is displayed

1) Try first to make HttpGet request, to get cookies, then perform HttpPost. I think this way you should not add cookies manually.
Use one HttpClient to do this.
2) Instead of
in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer sb = new StringBuffer("");
String line = "";
String NL = System.getProperty("line.separator");
while ((line = in.readLine()) != null)
{
sb.append(line + NL);
}
in.close();
resultContent = sb.toString();
use
EntityUtils.toString(response.getEntity()).

Related

Sending Https Request But Not Getting Response

I am sending Https request to mysql server but not getting the response while performing the same task on localhost it is working. I have no experience using Https, please give me solution and explain difference between Http and Https request sending to mysql server, hope someone help me thanks in advance.
This is my code
protected String doInBackground(String... params) {
String emailSend = params[0];
String tokenSend = params[1];
String deviceIdSend = params[2];
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("email", emailSend));
nameValuePairs.add(new BasicNameValuePair("token", tokenSend));
nameValuePairs.add(new BasicNameValuePair("deviceId", deviceIdSend));
try {
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost("https://xyz/xyz/xyz.php");
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpClient.execute(httpPost);
HttpEntity entity = response.getEntity();
is = entity.getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
result = sb.toString();
} catch (ClientProtocolException e) {
} catch (IOException e) {
}
return "success";
}
#Override
protected void onPostExecute(String resultN) {
super.onPostExecute(resultN);
String s = resultN.trim();
//dialog.dismiss();
if (s.equalsIgnoreCase("success")) {
if (result.contains("Pass")) {

Storing session cookie to maintain log in session

I've been trying to get this work for a while now. Im working on an app where the user signs in with a username and password which uses a httppost request to post to the server. i get the correct response, and during the post i store the session cookie that the server gives me. (I store it in a cookie store)
But when i try to click a link on the menu ( which does a second http post) after i logged in, the servers gives me a message saying that i am not logged in. But i send the cookie that i recieved in the first post to the server in the second post, yet the server does not recognize that i am logged in. To test this more easily i used the chrome plug in "Postman" which lets you post to websites easily. The only time it worked was when i log in to the website using chrome then use Postman to do the second post, which successfully gives me a response. however, when i use Postman to log in, then also use postman to attempt the second post , again, "Not logged in". Im guessing that the cookie is not being stored properly in the app. How could i go about fixing this? I read some stuff about storing the cookies in something called "Shared Preferences", is that possibly a fix? If so, what is it and how could i store the cookies there?
public static String executeHttpPost(String url, ArrayList<NameValuePair> postParameters) throws Exception {
BufferedReader in = null;
try {
LoginLayout.httpClient = new DefaultHttpClient();
HttpPost request = new HttpPost(url);
UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(postParameters);
request.setEntity(formEntity);
CookieStore cookiestore = LoginLayout.httpClient.getCookieStore();
HttpResponse response = LoginLayout.httpClient.execute(request);
List<Cookie> cookies = LoginLayout.httpClient.getCookieStore().getCookies();
cookiestore.addCookie(cookie);
cookie = cookies.get(0);
cookieValue = "ASPSESSIONIDCQTCRACT=" + cookiestore.getCookies();
System.out.println("The cookie" + cookieValue);
List<Cookie> cookiess = cookiestore.getCookies();
cookiee = cookies.get(0);
Header[] headers = response.getAllHeaders();
System.out.println("length" + headers.length);
for (int i=0; i < headers.length; i++) {
Header h = headers[i];
System.out.println( "Header names: "+h.getName());
System.out.println( "Header Value: "+h.getValue());
}
in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer sb = new StringBuffer("");
String line = "";
String NL = System.getProperty("line.separator");
while ((line = in.readLine()) != null) {
sb.append(line + NL);
}
in.close();
// System.out.println( mCookie);
String result = sb.toString();
return result;
}
finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} }
Here is the getter so i can access the cookie from the cookie store in the next activity
public static String getCookie(){
return cookiee.getName() +"="+cookiee.getValue();
}
Here is the second post where i try to retrieve the stored cookie, which it seems to do sucessfully, however the server doesnt recognize i am logged in
public static String executeHttpPost(String url, ArrayList<NameValuePair> postParameters) throws Exception {
BufferedReader in = null;
try {
HttpPost request = new HttpPost(url);
request.setHeader("Cookie", LoginLayout.getCookie());
UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(postParameters);
request.setEntity(formEntity);
HttpResponse response = LoginLayout.httpClient.execute(request);
Header[] headers = response.getAllHeaders();
System.out.println("length" + headers.length);
for (int i=0; i < headers.length; i++) {
Header h = headers[i];
System.out.println( "Header names: "+h.getName());
System.out.println( "Header Value: "+h.getValue());
}
in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer sb = new StringBuffer("");
String line = "";
String NL = System.getProperty("line.separator");
while ((line = in.readLine()) != null) {
sb.append(line + NL);
}
in.close();
//System.out.println( mCookie);
String result = sb.toString();
return result;
}
finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
You have to make sure that your HttpClient is using the same HttpContext on each request.
The CookieStore is associated with the HttpContext so create a new instance of HttpContext will create a new CookieStore as well.
The best way I found is to create a static instance of HttpContext and use it on every request.
Below I added an part of a class I'm using in my apps:
public class ApiClient {
// Constants
private final static String TAG = "ApiClient";
private final static String API_URL = "your-url";
// Data
private static ApiClient mInstance;
private HttpClient mHttpClient;
private ThreadSafeClientConnManager mConnectionManager;
private HttpPost mPost;
/*
* we need it static because otherwise it will be recreated and the session
* will be lost
*/
private static HttpContext mHttpContext;
private HttpParams mParams;
private Context mContext;
public ApiClient(Context pContext) {
mParams = new BasicHttpParams();
mContext = pContext;
if (null == mHttpContext) {
CookieStore cookieStore = new BasicCookieStore();
mHttpContext = new BasicHttpContext();
mHttpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
}
ConnManagerParams.setMaxTotalConnections(mParams, 300);
HttpProtocolParams.setVersion(mParams, HttpVersion.HTTP_1_1);
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
mConnectionManager = new ThreadSafeClientConnManager(mParams, schemeRegistry);
mHttpClient = new DefaultHttpClient(mConnectionManager, mParams);
}
public static ApiClient getInstance(Context pContext) {
if (null == mInstance) {
return (mInstance = new ApiClient(pContext));
} else {
return mInstance;
}
}
public void testPOST() {
List<NameValuePair> requestParams = new ArrayList<NameValuePair>();
requestParams.add(new BasicNameValuePair("param1", "value1"));
requestParams.add(new BasicNameValuePair("param2", "value2"));
mPost = new HttpPost(API_URL);
try {
mPost.setEntity(new UrlEncodedFormEntity(requestParams, HTTP.UTF_8));
HttpResponse responsePOST = mHttpClient.execute(mPost, mHttpContext);
HttpEntity resEntity = responsePOST.getEntity();
String result = EntityUtils.toString(resEntity);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
To test it try setting the correct API_URL and
ApiClient api = ApiClient.getInstance(somContext);
api.testPOST();

Enable cookies with HTTPClient

I am trying to implement a Java Code that fetch urls like this one:
http://trendistic.indextank.com/_trending-topics-archive/2011-12-25
The code I wrote is based in HTTPClient as follow:
HttpClient httpclient = new DefaultHttpClient();
// Create a local instance of cookie store
CookieStore cookieStore = new BasicCookieStore();
// Create local HTTP context
HttpContext localContext = new BasicHttpContext();
// Bind custom cookie store to the local context
localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
HttpGet httpget = new HttpGet(urls);
try {
System.out.println("executing request " + httpget.getURI());
HttpResponse response = httpclient.execute(httpget, localContext);
String line = "";
StringBuilder total = new StringBuilder();
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
while ((line = rd.readLine()) != null) {
total.append(line+"\n");
}
System.out.println(total);
return (total.toString());
} catch (Exception e) {
e.printStackTrace();
return(e.getMessage());
}
}
Nevertheless, the response I got is:
if (tz != tzless.readCookie('local_tz')) {
// no cookies!
document.write("<h1>Cookies are not enabled for this site</h1>");
document.write("<p>In order for Trendistic to work in Internet Explorer you need to enable cookies.</p>");
document.write("<ul><li>Please enable cookies for this site and refresh this page</li><li>Or try Trendistic in a different browser such as Safari, Firefox or Chrome.</li></ul>");
} else {
self.location.reload();
}
How can I enable cookies for fetching the HTML with the dynamical results.

Android c2dm server simulator on emulator

I am following android c2dm example from following link:
http://www.vogella.de/articles/AndroidCloudToDeviceMessaging/article.html
I have implemented the client side successfully and have got my registration id. but i am having some issues in server end using the same example actually the issue is in getAuthentification method and i am getting following exception at HttpResponse response = client.execute(post).
java.net.UnknownHostException: www.google.com
Following is my code:
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(
"https://www.google.com/accounts/ClientLogin");
try {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
nameValuePairs.add(new BasicNameValuePair("Email","you....#gmail.com"));
nameValuePairs.add(new BasicNameValuePair("Passwd","*********"));
nameValuePairs.add(new BasicNameValuePair("accountType", "GOOGLE"));
nameValuePairs.add(new BasicNameValuePair("source",
"Google-cURL-Example"));
nameValuePairs.add(new BasicNameValuePair("service", "ac2dm"));
post.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = client.execute(post);
BufferedReader rd = new BufferedReader(new InputStreamReader(
response.getEntity().getContent()));
String line = "";
while ((line = rd.readLine()) != null) {
Log.e("HttpResponse", line);
if (line.startsWith("Auth=")) {
Editor edit = prefManager.edit();
edit.putString(AUTH, line.substring(5));
edit.commit();
String s = prefManager.getString(AUTH, "n/a");
Toast.makeText(this, s, Toast.LENGTH_LONG).show();
}
}
} catch (IOException e) {
e.printStackTrace();
}
Please help me? Your help would be highly appreciable. Thanks,
I had this exact same issue last week. When the C2DM servers return a 302 Moved (www.google.com) what they ACTUALLY mean is the authentication failed. The problem is almost certainly your authentication code, so re-check the code you're using to get the auth code from the ClientLogin API. Note that the HTTP response contains a bunch of information, not just the auth code, so you do need to parse it correctly (that was my mistake).
public static String getClientLoginAuthToken(String email, String password) {
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost("https://www.google.com/accounts/ClientLogin");
try {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
nameValuePairs.add(new BasicNameValuePair("Email", email));
nameValuePairs.add(new BasicNameValuePair("Passwd", password));
nameValuePairs.add(new BasicNameValuePair("accountType", "GOOGLE"));
nameValuePairs.add(new BasicNameValuePair("source","Google-cURL-Example"));
nameValuePairs.add(new BasicNameValuePair("service", "ac2dm"));
post.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = client.execute(post);
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
String line = "";
while ((line = rd.readLine()) != null) {
if (line.startsWith("Auth=")) {
return line.substring(5);
}
}
} catch (IOException e) {
e.printStackTrace();
}
Log.e(TAG, "Failed to get C2DM auth code");
return "";
}

Set cookie from HTTP Request

I have get a correct login using HttpRequest to work. It prints the correct html form of the logn page in my toast (just for testing). Now I want to set a cookie from that request. How is this possible?
If it necessary I can provide some code.
I already know about the CookieManager class, but how can I successfully do it?
Thanks in advance!
My code:
public String getPostRequest(String url, String user, String pass) {
HttpClient postClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
HttpResponse response;
try {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("login", user));
nameValuePairs.add(new BasicNameValuePair("pass", pass));
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, HTTP.UTF_8));
response = postClient.execute(httpPost);
if(response.getStatusLine().getStatusCode() == 200) {
HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream instream = entity.getContent();
String result = convertStreamToString(instream);
instream.close();
return result;
}
}
} catch (Exception e) {}
Toast.makeText(getApplicationContext(),
"Connection failed",
Toast.LENGTH_SHORT).show();
return null;
}
private String convertStreamToString(InputStream is) {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}
Well, this is pretty much it. convertStreamToString() function converts the InputStream into a String (plain HTML code), which I "toast" out to just test it (so it work), so the code is working though. Now to set the cookie. :-)
This is what I've reached for now:
// inside my if (entity != null) statement
List<Cookie> cookies = postClient.getCookieStore().getCookies();
String result = cookies.get(1).toString();
return result;
When I have logged in, the CookieList id 1 contains a value, otherwise the value is standard. So for now I know the difference in value, but how can I continue?
I think Android ships with Apache HttpClient 4.0.
You can check Chapter 3. HTTP state management topic from HttpClient Tutorial.
You can also refer similar questions on SO:
Android project using httpclient --> http.client (apache), post/get method
How do I manage cookies with HttpClient in Android and/or Java?
Also Check this example for usage: http://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.0.x/httpclient/src/examples/org/apache/http/examples/client/ClientFormLogin.java

Categories