NTLM Authentication with HttpURLConnection - android

Is there any way to implement NTLM Authentication with HttpURLConnection? Currently I have implemented it with DefaultHttpClient and JCIFSEngine for the authentication scheme. ( My inspiration was : Android: NTLM Authentication, ksoap, and persistent connections)
But since Android 6 Apache HTTP Client Removal, I was looking for a solution besides adding useLibrary 'org.apache.http.legacy' in app gradle file, cause I want to improve my code using HttpURLConnection class instead. As documentation says, this API is more efficient because it reduces network usage through transparent compression and response caching, and minimizes power consumption.

HttpURLConnection can work with NTLM only if you add library jcifs.
This example works with latest jcifs-1.3.18 :
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map;
import org.apache.http.impl.auth.NTLMEngineException;
public class TestNTLMConnection {
public static void main(String[] args) throws UnknownHostException, IOException, NTLMEngineException {
// Method 1 : authentication in URL
jcifs.Config.registerSmbURLHandler();
URL urlRequest = new URL("http://domain%5Cuser:pass#127.0.0.1/");
// or Method 2 : authentication via System.setProperty()
// System.setProperty("http.auth.ntlm.domain", "domain");
// System.setProperty("jcifs.smb.client.domain", "domain");
// System.setProperty("jcifs.smb.client.username", "user");
// System.setProperty("jcifs.smb.client.password", "pass");
// Not verified // System.setProperty("jcifs.netbios.hostname", "host");
// System.setProperty("java.protocol.handler.pkgs", "jcifs");
// URL urlRequest = new URL("http://127.0.0.1:8180/simulate_get.php");
HttpURLConnection conn = (HttpURLConnection) urlRequest.openConnection();
StringBuilder response = new StringBuilder();
try {
InputStream stream = conn.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(stream));
String str = "";
while ((str = in.readLine()) != null) {
response.append(str);
}
in.close();
System.out.println(response);
} catch(IOException err) {
System.out.println(err);
} finally {
Map<String, String> msgResponse = new HashMap<String, String>();
for (int i = 0;; i++) {
String headerName = conn.getHeaderFieldKey(i);
String headerValue = conn.getHeaderField(i);
if (headerName == null && headerValue == null) {
break;
}
msgResponse.put(headerName == null ? "Method" : headerName, headerValue);
}
System.out.println(msgResponse);
}
}
}
Warning: jcifs ignores the connectTimeout and readTimeout you define with the library, it's the reason why the connection takes ages to break when the host is not responding. Use the code I describe in this SO thread to avoid this bug.

Related

how to connect android to restful api

I'm making an app which let people login, sign in, sign up, write something and save it to database.
So I decided to chose Restful Api with Slim Framework. I publish it in my host and test by extension of google chrome call Advanced Rest Client. Everything like login ,signin, sign up, wite something, update it, delete it.. work fine.
For example:
I log in with information:
email: stark#gmail.com
password: abc
then the result is something like that.
{
error: false
name: "Kien"
email: "nguyenkien1402#yahoo.com"
apiKey: "fc2aee103c861026cb53fd8920b10adc"
createdAt: "2015-06-24 00:28:01"
}
But when I used it in my android app. I cannot connect and get information by JSON.
Please tell my how to solve this problem.
Thank you.
Sorry about my english, it's not native english.
To connect to the restful API, the following steps you have to do
give internet access
have to do http connection
have to to take stream input
Give Internet Access
to give internet access to the app we have to add this piece of code in the file " AndroidManifest.xml"
<uses-permission android:name="android.permission.INTERNET"/>
To do the second and third step we have to create a new java class as when we are connecting to the restful API, it will run in the background and MainActivity does not allow the background task.
Let say we create a new java class "fetchData" to get data from the API.
to do the remaining task we have to use this piece of code
URL url = new URL(API ADDRESS);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
InputStream inputStream = httpURLConnection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
now you get the JSON file using the "Bufferedreader.readLine()"
then the class file looks like this
import android.os.AsyncTask;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class fetchData extends AsyncTask<Void,Void,Void> {
String data ="";
String dataParsed = "";
String singleParsed ="";
#Override
protected Void doInBackground(Void... voids) {
try {
URL url = new URL("https://api.myjson.com/bins/k3p10");
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
InputStream inputStream = httpURLConnection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String line = "";
while(line != null){
line = bufferedReader.readLine();
data = data + line;
}
JSONArray JA = new JSONArray(data);
for(int i =0 ;i <JA.length(); i++){
JSONObject JO = (JSONObject) JA.get(i);
singleParsed = "Name:" + JO.get("name") + "\n"+
"email:" + JO.get("email") + "\n"+
"Error:" + JO.get("error") + "\n";
dataParsed = dataParsed + singleParsed +"\n" ;
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
}
}
from the JSON array, you can extract everything from the JSON you get from the API. then you can use the information as per your requirement.
If your url is generating json response, then you have to read that.
public static String sendGet(String url) throws Exception {
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
// optional default is GET
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
System.out.println("\nSending 'GET' request to URL : " + url);
System.out.println("Response Code : " + responseCode);
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
return response.toString(); //here is your response which is in string type, but remember that the format is json.
}
Then convert your response to json:
JsonObject obj = new JsonObject(response);
I solved it.
It up to my class about CRUD JSON.
Thank you.

How to get restaurant menus from Locu API

I have looked at several APIs for acquiring restaurant menu for a particular location and determined that Locu API works best for me.
I was trying the basic example listed on locu website:
curl -X POST https://api.locu.com/v2/venue/search/ -d '{"fields":["name","menu_items","location","categories","description"],"menu_item_queries":[{"price":{"$lt":6},"name":"burrito"}],"venue_queries":[{"location":{"locality":"San Francisco"}}],"api_key":"MY_API_KEY"}'
Where, MY_API_KEY is the API_KEY that I received when I signed up.
As long as I include "menu_items" parameter, I keep getting the response:
{"status": "error", "http_status": 400, "error": "The requested \"menu_items\" field is either invalid or your account does not have permissions to access it."}
I did not come across any documentation regarding what I need to do in order to get the permissions for querying "menu_items". If anyone could point me in the right direction, I will really appreciate that.
I have already gone through some relatively old questions on here and they did not address this particular issue.
Also, there doesn't seem to be a tag for Locu api here. I am going to try and tag the question with some generic tags. Please excuse me for that.
I know this is an old question, but I've found that the solution is to request the "menus" field in a venue search. The API will return the "menu_items" as sub-objects of the menus.
`
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class NetClientGet {
public static void main(String[] args) {
try{
String result;
URL url = new URL("https://api.locu.com/v1_0/venue/search/?api_key=" +apiKey);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Accept", "application/json");
if (conn.getResponseCode() != 200) {
throw new RuntimeException("Failed : HTTP error code : " + conn.getResponseCode());
}
BufferedReader br = new BufferedReader(new InputStreamReader(
(conn.getInputStream())));
String output;
System.out.println("Output from Server .... \n");
while ((output = br.readLine()) != null) {
System.out.println(output);}
}
conn.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}`

Parse incoming http post request java android

I am working on an Android web server.When i go to localhost:8080 on the emulator browser, it serves a page/form with a password field. On successful verification of the password, I would like to redirect the user to the success/failure page.What would be the best way to read the incoming http post request and parse the password field for verification?Any pointers in the right direction would be greatly appreciated. I have a handler for the url to which the form is submitted. The code for the handler is:
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import org.apache.http.HttpEntity;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.entity.ContentProducer;
import org.apache.http.entity.EntityTemplate;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpRequestHandler;
import android.content.Context;
public class LoginHandler implements HttpRequestHandler {
private Context context = null;
public LoginHandler(Context context) {
this.context = context;
}
#Override
public void handle(final HttpRequest request, HttpResponse response,
HttpContext httpcontext) throws HttpException, IOException {
HttpEntity entity = new EntityTemplate(new ContentProducer() {
public void writeTo(final OutputStream outstream) throws IOException {
String resp = null;
OutputStreamWriter writer = new OutputStreamWriter(outstream, "UTF-8");
if(validatePassword()==true){
resp ="<html><head></head><body><h1>Home<h1><p>Success.</p></body></html>";
}
else{resp="<html><head></head><body><h1>Home<h1><p>Login Failed.</p></body></html>";}
writer.write(resp);
writer.flush();
}
});
response.setHeader("Content-Type", "text/html");
response.setEntity(entity);
}
boolean validatePassword(){
boolean pass=false;
//parse request body here and check for the password if true return true/else false
return pass;
}
}
After looking around for ages I found the solution. Adding the following in the handle method does the trick.Thanks to the original poster
.http://www.androiddevblog.net/android/a-bare-minimum-web-server-for-android-platform
if (request instanceof HttpEntityEnclosingRequest) {
HttpEntity entity = ((HttpEntityEnclosingRequest) request).getEntity();
if (entity != null) {
Log.v("RequestBody", EntityUtils.toString(entity, "UTF-8"));
entity.consumeContent();
}
}
I apologize if this isn't quite what you're asking, so if it's not, let me know.
You could use a JSONObject to return whether or not that password was verified as correct.
For example, if the password is correct, you could store the HTTP result as:
{"status":200,"confirmed":"true"}
Or "false" otherwise.
When you get back from the HTTP Post Request, you can store this result as a String, then make a JSONObject out of it. For example:
// Send the URL to a postRequest function and return the result as a String
String output = makePostRequest(url);
// Parse the String as a JSONObject and receive whether or not the login was confirmed
JSONObject o = new JSONObject(output);
String confirmed = o.getString("confirmed");
if (confirmed.equals("true")) {
// Password confirmed - redirect user to success page
} else {
// Password incorrect - redirect user to failure page
}
Note: in case you need an idea of how to receive the response code from the post request, here's some sample code:
String output = {};
// Use bufferedreader and stringbuilder to build an output string (where conn is your HTTPUrlConnection object you used to make the post request
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
StringBuilder sb = new StringBuilder();
String line;
// Loop through response to build JSON String
while((line = br.readLine()) != null) {
sb.append(line + "\n");
}
// Set output from response
output = sb.toString();
And now output is the String you can turn into a JSONObject.
Does any of this help?
Edit:
Okay, so the String you will be getting will be in the format of {"password":"somepassword"}. To parse this, try this out:
String s = /* the string in the format {"password":"somepassword"} */
JSONObject o = new JSONObject(s);
String password = o.getString("password");
if (password.equals(random_password_at_beginning_of_webservice) {
// Password confirmed - redirect user to success page
} else {
// Password incorrect - redirect user to failure page
}

Get content of HTTPS GET request in Android

I have the following code which takes a normal HTTP GET Request and returns the output html as a string.
public static String getURLContent(String URL){
String Result = "";
String IP = "http://localhost/";
try {
// Create a URL for the desired page
URL url = new URL(IP.concat(URL));
// Read all the text returned by the server
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
String str;
while ((str = in.readLine()) != null) {
// str is one line of text; readLine() strips the newline character(s)
Result = Result+str+"~";
}
in.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return Result;
}
I would like to implement the same sort of thing for an unsigned ssl certificate but I am a bit of a novice at Java or Android programming and find some previous responses to similar questions very confusing.
Could someone change the code above to work with HTTPS requests?
One other question, would there be a risk of a middle-man-attack if I sent unencrypyted data via the GET request and print out database entries onto the webpage that the function returns the content of. Would it be better to use a POST request?
The reason I chose to use SSL is because someone told me that the data sent is encrypted. The data is sensitive and if I send something like localhost/login.php?user=jim&password=sd7vbsksd8 which would return "user=jim permission=admin age=23" which is data that I don't want others to see if they simply used a browser and sent the same request.
Try this:
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URI;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
public class TestHttpGet {
public void executeHttpGet() throws Exception {
BufferedReader in = null;
try {
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet();
request.setURI(new URI("http://w3mentor.com/"));
HttpResponse response = client.execute(request);
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();
String page = sb.toString();
System.out.println(page);
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
We can add parameters to an HTTP Get request as
HttpGet method = new HttpGet("http://w3mentor.com/download.aspx?key=valueGoesHere");
client.execute(method);
Android should automatically work with ssl. Maybe ssl certificate you are using on localhost is not trusted? Check this: Trusting all certificates using HttpClient over HTTPS
Check if you are able to browse https://yourhost/login.php?user=jim&password=sd7vbsksd8 using your browser.

Replacement for deprecated Google web search API for Android

I'm looking to search Google from my Android app and return results. Everything I've found points towards the Google Web Search API which the page now says is deprecated and is being replaced by a Custom Search API.
The new custom search API only allows you to search through websites you've created a custom search engine for. I want to search all of the internet as anyone would through Google.
How can I do this?
Android has a lot of search capabilities - all built-in.
Look here:
http://developer.android.com/guide/topics/search/index.html
Google Code and the Android SDK are two different things. The Web Search API is Google Code and, and you noted, it has indeed been deprecated in favor of Google Custom Search:
http://code.google.com/apis/customsearch/v1/overview.html
http://www.google.com/cse/
Finally, here's a good blog entry that shows you how to invoke a Bing/Yahoo! web search from Android:
http://www.codexperiments.com/java/2011/01/create-your-own-web-search-application/
Frankly, the Bing API looks a heck of a lot better than Google Custom Search. Starting with the fact that Bing's API doesn't limit you to 100 queries/day like Custom Search does :)
'Hope that helps!
You can Bing search API -
First you need to create an account at Microsoft and get an account key, then use it as follows:
import android.os.AsyncTask;
import android.util.Log;
import org.apache.commons.codec.binary.Base64;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
/**
* Created by Asaf on 08/06/2014.
*/
public class SearchAsyncTask extends AsyncTask<Void, Void, Void> {
private final String TAG = getClass().getName();
#Override
protected Void doInBackground(Void... params) {
try {
String bingUrl = "https://api.datamarket.azure.com/Bing/SearchWeb/v1/Web?Query=%27pinhassi%27";
String accountKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
byte[] accountKeyBytes = Base64.encodeBase64((accountKey + ":" + accountKey).getBytes());
String accountKeyEnc = new String(accountKeyBytes);
URL url = null;
url = new URL(bingUrl);
URLConnection urlConnection = url.openConnection();
urlConnection.setRequestProperty("Authorization", "Basic " + accountKeyEnc);
InputStream response = urlConnection.getInputStream();
String res = readStream(response);
Log.d(TAG, res);
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, e.getMessage());
}
return null;
}
private String readStream(InputStream in) {
BufferedReader reader = null;
StringBuilder sb = new StringBuilder();
try {
reader = new BufferedReader(new InputStreamReader(in));
String line = "";
while ((line = reader.readLine()) != null) {
//System.out.println(line);
sb.append(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return sb.toString();
}
}

Categories

Resources