Server in Java(Http/sockets) - android

I want to build an Http Server which will serve the requests of a chat application in android. Because i am really confused... in my code I have to use sockets? How can i make the client to communicate with the server? Which is the code i have to add in the server in order to accept the requests from the client and respond to them? The code I use in the client is the following:
DefaultHttpClient client = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://localhost:80");
List< BasicNameValuePair > nvps = new ArrayList< BasicNameValuePair >();
nvps.add(new BasicNameValuePair("username", username1));
nvps.add(new BasicNameValuePair("password", password1));
try {
UrlEncodedFormEntity p_entity = new UrlEncodedFormEntity(nvps, HTTP.UTF_8);
httppost.setEntity(p_entity);
//Execute HTTP Post Request
HttpResponse response = client.execute(httppost);
Log.v(TAG,"something");
Log.v(TAG, response.getStatusLine().toString());
HttpEntity responseEntity = response.getEntity();
Please I really need an answer. Thank you!!!

Sockets (Socket for client, ServerSocket for server) is the most basic layer of communication. You chose TCP or UDP and over it, you need to encode all of your protocol.
There are also some libraries that encode higher level protocols (HTTP, FTP, and even higher as SOAP). If you use these libraries, you usually do not need to manage socket as it is done by the library itself (in the server you only specify port and optionally IP to bind to; in the client you specify host and port to connect to).
You can use different combinations (v.g. implementing your server with SOAP and then creating and sending a SOAP message from the client using Socket) but the simplest way is to use the same library both for the server and client.
About which one is better: it depends of what you want it to. Higher level libraries are more flexible but may take a time to master and may have more overhead, lower level needs that you manage everything. If there is no more compelling reason, I usually just use the HTTP protocol (both from the JVM or from the Apache Foundation projects).

Related

MVC4 - Android authentication via http POST and FormsAuthentication

I know there are plenty of resources like this on the web, and the closest I've come was the answer to this question: ASP.NET Web API Authentication.
Basically, this is my requirement. Log in via android to my account on an MVC4 internet application I created (which uses SimpleMembership). It is NOT an MVC Web Api app, which seems to confuse things when looking at the various ways of achieving this.
I am attempting to use FormsAuthentication to set an authentication cookie, but I have no idea how to configure my android httpclient to actually send through this authentication cookie, or how to get MVC to save a session from my android app.
So far, this is what I've come up with on the MVC side:
[HttpPost]
[AllowAnonymous]
public bool LoginMobi(LoginModel model)
{
var membership = (SimpleMembershipProvider)Membership.Provider;
if (membership.ValidateUser(model.UserName, model.Password))
{
FormsAuthentication.SetAuthCookie(model.UserName, false);
return true;
}
else return false;
}
And I use the following java in my android app (sent over an SSL connection):
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("https://mysite/api/login");
List<NameValuePair> nameValue = new ArrayList<NameValuePair>();
nameValue.add(new BasicNameValuePair("UserName", "foo"));
nameValue.add(new BasicNameValuePair("Password", "bar"));
httppost.setEntity(new UrlEncodedFormEntity(nameValue));
httppost.setHeader("Content-type", "application/json");
HttpResponse response = httpclient.execute(httppost);
// etc etc
What I haven't figured out is how to receive the authentication cookie on android and send it back with each request to controllers with the [Authorize] attribute. I'm rather new to this so please forgive my ignorance!
You are using FormsAuthentication which uses cookie to identify user for each request. You have two options here.
Use CookieStore for HttpClient. Check Android HttpClient and Cookies
OR
Combine BASIC auth and FormsAuthentication. Check Combining Forms Authentication and Basic Authentication
Hope this helps.

Android: HttpClient remote vs. local server

I'm having problems with an app that works when connecting to a remote web server, running a php script against a database. However, when I point the same app to my local web server running on my machine, things doesn't work.
Here's the code I use for connecting to the remote web server (it needs authentication):
(All the networking code is done inside an AsyncTask class.)
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(url);
StringBuilder authentication = new
StringBuilder().append("frankh").append(":").append("vriceI29");
result = Base64.encodeBytes(authentication.toString().getBytes());
httppost.setHeader("Authorization", "Basic " + result);
nameValuePairs.add(new BasicNameValuePair("date", date));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
is = entity.getContent();
For the connection to the local server, which doesn't use authentication, I'm commenting out these lines:
//StringBuilder authentication = new
// StringBuilder().append("frankh").append(":").append("vriceI29");
//result = Base64.encodeBytes(authentication.toString().getBytes());
//httppost.setHeader("Authorization", "Basic " + result);
However, I get two different errors, depending on how I phrase the url to the local web server.
If I use this url: "http://localhost.shoppinglistapp/fetchlist.php"
I get this error:
Error in http connectionjava.net.UnknownHostException: localhost.shoppinglistapp
If I skip the http part in the url, I get this error:
Error in http connectionjava.lang.IllegalStateException: Target host must not be null,
or set in parameters.
What am I doing wrong here? The remote server is a Linux Apache server, and the local server is IIS 7. The local server is supposed to be just for working on when I've got no or a bad internet connection, so it's not critical, but I hate not knowing why things doesn't work.
If you testing via your local emulator, you'll want to use 10.0.2.2 instead of 'localhost'.
Referring to localhost from the emulated environment

TLS with Server Name Indication extension (RFC 3546) in Android

I am building a Android app that needs to work with https. I have no problem doing a https connection to a https address that do not use TLS with Server Name Indication extension. But I need to do the connection to a https address that uses TLS with SNI extension.
What I did for https address that uses TLS with out hostname extension was:
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("https://exampleurl.com/api");
try {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("username", email));
nameValuePairs.add(new BasicNameValuePair("ssh_public_key", publickey));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
Log.d(TAG, response.toString());
return response.toString();
} catch (Exception e) {
Log.d(TAG, e.toString());
}
How do I add Server Name Indication extension in the TLS in Android. After research I found one post on stackoverflow but I cant get it to work with this information.
But its a bit on the way
"As far as I know, there is a partial support in Android SDK. The current situation is the following:
Since the Gingerbread release TLS connection with the HttpsURLConnection API supports SNI.
Apache HTTP client library shipped with Android does not support SNI
The Android web browser does not support SNI neither (since using the Apache HTTP client API)"
"Thanks for the help. I have tried the sni.velox.ch link using SSLCONTEXT(TLS) and SSLENGINE class available in the android sdk. I am getting the handshake."
Android SSL - SNI support
This post gives the answer that this will work in Android but I cant get how to do it with HttpsURLConnection, SSLCONTEXT(TLS) and SSLENGINE.
Can any body provide an code example of how to set the Server Name Indication extension in the TLS?

Android app getting data from a third-party JSP & Servlet

I'm writing an Android app that should get data from a certain web application. That web app is based on Servlets and JSP, and it's not mine; it's a public library's service. What is the most elegant way of getting this data?
I tried writing my own Servlet to handle requests and responses, but I can't get it to work. Servlet forwarding cannot be done, due to different contexts, and redirection doesn't work either, since it's a POST method... I mean, sure, I can write my own form that access the library's servlet easily enough, but the result is a jsp page.. Can I turn that page into a string or something? Somehow I don't think I can.. I'm stuck.
Can I do this in some other way? With php or whatever? Or maybe get that jsp page on my web server, and then somehow extract data from it (with jQuery maybe?) and send it to Android? I really don't want to display that jsp page in a browser to my users, I would like to take that data and create my own objects with it..
Just send a HTTP request programmatically. You can use Android's builtin HttpClient API for this. Or, a bit more low level, the Java's java.net.URLConnection (see also Using java.net.URLConnection to fire and handle HTTP requests). Both are capable of sending GET/POST requests and retrieving the response back as an InputStream, byte[] or String.
At most simplest, you can perform a GET as follows:
InputStream responseBody = new URL("http://example.com").openStream();
// ...
A POST is easier to be performed with HttpClient:
List<NameValuePair> params = new ArrayList<NameValuePair>(2);
params.add(new BasicNameValuePair("name1", "value1"));
params.add(new BasicNameValuePair("name2", "value2"));
HttpPost post = new HttpPost("http://example.com");
post.setEntity(new UrlEncodedFormEntity(params));
HttpClient client = new DefaultHttpClient();
HttpResponse response = client.execute(post);
InputStream responseBody = response.getEntity().getContent();
// ...
If you need to parse the response as HTML (I'd however wonder if that "public library service" (is it really public?) doesn't really offer XML or JSON services which are way much easier to parse), Jsoup may be a life saver as to traversing and manipulating HTML the jQuery way. It also supports sending POST requests by the way, only not as fine grained as with HttpClient.

rails Devise http authenticating mobile

I'm trying to authenticate an android client app to my server ruby on rails app which uses Devise gem. But I've tried http authentication, and post requests to authenticate, and the server just responds 200 for any given username/password.
I've already set up the config.http_authenticatable = true and the :database_authenticable at the user model...
I'll post my authenticate method so u guys can have a look on it...
public static boolean authenticate(User user, String verb) throws IOException, JSONException
{
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(verb);
CredentialsProvider credProvider = new BasicCredentialsProvider();
credProvider.setCredentials(new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT),
new UsernamePasswordCredentials(user.getMail(), user.getPassword()));
httpClient.setCredentialsProvider(credProvider);
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("email", user.getMail()));
nameValuePairs.add(new BasicNameValuePair("password", user.getPassword()));
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse httpResponse = httpClient.execute(httpPost);
int statusCode = httpResponse.getStatusLine().getStatusCode();
//JSONObject resp = null;
if (statusCode < 200 || statusCode >= 300){
throw new IOException("Error");
}
return true;
}
If server is responding 200, it really sounds like server side configuration, so you should double-check your URLs are actually secured, using a desktop web browser and a tool like Fiddler so you can see everything. Pay particular attention to the Authentication headers, and the Status codes; at the least you should see a 401 from the server to start things off.
You can also turn on diagnostics for Apache HTTP on your device, and it will also dump headers and content to LOGCAT, so you can make sure everything is proceeding.
Check the WWW-Autnenticate header's contents, it will specify which schemes are accepted. The client side will re-request the URL, but it will put the Authorization header into its request.
In short, make sure your server side works outside of your application, in an environment that's easier to troubleshoot.
Client side, it looks like you are only activating BASIC authentication (everyone stop using it!), and your endpoint may only want DIGEST or NTLM or KERBEROS or any other authentication scheme than BASIC. Since it looks like you didn't set up for SSL, certainly use at least DIGEST or you have clear text issues!
Using form variables (for authentication) only works at the application level, and not the HTTP protocol level, which uses HTTP Headers (WWW-Autnenticate, Authorization) and Status codes (401, 403) for the authentication process. And again, if you aren't configuring your server (and client) for SSL-only, there will be clear text problems.

Categories

Resources