I'm implementing an android app and I'm having trouble understanding how I can implement a login feature (very simple, no encryption needed) and how it works after the user logs in
So, the first thing to do is make a Request, I send the login, and password,with an http POST method probably?
and the server replies with a token of some sort, correct?
Then I save that token, and what happens next? I have a bunch of pages I need to make GET requests on, but I also need to send the token someway, right?
How exactly can I make that?
thank you
You pretty much have it summed up I guess. Let the app send the credentials with a POST, the server checks if they are okay, then sends back a token (some random String maybe). When you make the GET requests after login, send the token with a custom HTTP header and let the server check it. The server has a list of valid tokens and checks if the received token is valid. If not, it responds with an error message, else it does what it's supposed to do.
That's all very basic and not at all secure of course.
Edit: The GET request could be done like this:
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet("someUrl.com/rest");
get.setHeader("Authorization", "someTokenYouCreated");
HttpResponse response = client.execute(get);
You'll find lot's of examples about calling a REST method. You'll have to look up how to handle that header on the server side, but that can't be too difficult either.
Related
I have an user authentication API which returns an object containing some data including status code, for ex. 200.Even if the credentials are incorrect i am sending 200 status message but the response object's status field has status 401 and message "Incorrect Credentials".So my question is, which response is proper?The one where even when the credentials are incorrect i am sending 200 status message and then inside the response object i have to check again for whether the credentials were correct or not or second where if the credentials are incorrect i am sending status 401 along with the response object?
I think it's better to return it in the HTTP header. In this way the client can know that an error has ocurred in an easier way. In the end it is more straightforward.
Preferable way is propably to return the http status and code in the header. This way the user can use native methods to react to the responses. In case there is a unexpected error in your service and you cannot form a pretty response object out of it, the user is still able to handle it since the response will have the proper HTTP status code. If the user always expects your API to return an object, he/she is in trouble in that situation. Of course, you could tell them to take that into account, but then the user would have to implement additional logic to handle two kind of responses.
But:
You could do something like I did: Let the user choose!
I put a variable in the url that tells the service whether to return the http response with proper codes or not.
The url looks something like this:
/some_path/{real_http_code}/some_path_or_data
Where the {real_http_code} is a true/false -text. If it's true, our service knows to return the response with the proper HTTP status code. If false, service will always return 200 OK -response, and the user has to check the response if something went wrong.
So, the url could look something like this:
/some_path/true/some_path_or_data
Ups and downs:
+Gives the user the freedom to choose
-Additional logic must be implemented into the service
I'm in the process of learning how to use HP Quality Center's REST api to query and manipulate data. Unlike REST standard, this API is not completely stateless. It uses cookies to store authentication sessions.
I've tried to implement a very simple test, using the Jersey Client library. I can successfully authenticate my user, by sending my credentials. The API reference claims that this will set a cookie, and I am good to go with further calling the REST api. However, a simple "is-authenticated" call returns a 401, Authentication failed.
I have a feeling that the cookie writing or reading is not working properly, as everything else seems to work as it should. But I haven't been able to find out if or how cookies are set and read, when no browser is involved. So How does cookies work, when calling cookie-setting REST services from java VM? Does it work at all? Where are they stored?
I am using Eclipse Kepler as my IDE, if that matters at all, and a 32-bit java 1.6 JDK and JRE.
Code, and response strings below:
1. Logging in:
Client client = ClientBuilder.newClient();
Response response = client
.target("http://[host]:[port]").path("qcbin/authentication-
point/alm-authenticate")
.request().post(Entity.entity("<alm-authentication>
<user>username</user>
<password>secret</password></alm-authentication>",
MediaType.TEXT_XML_TYPE));
System.out.println(response.toString());
Output:
InboundJaxrsResponse{ClientResponse{method=POST,
uri=http://[host]:[port]/qcbin/authentication-point/alm-authenticate,
status=200, reason=OK}}
API Return description:
One of:
HTTP code 200 and sets the LWSSO cookie (LWSSO_COOKIE_KEY).
HTTP code 401 for non-authenticated request. Sends header
WWW-Authenticate: ALMAUTH
2. Verifying Logged in:
response = client.target("http://[host]:[port]")
.path("qcbin/rest/is-authenticated")
.request().get();
System.out.println(response.toString());
Output:
InboundJaxrsResponse{ClientResponse{method=GET,
uri=http://[host]:[port]/rest/is-authenticated, status=401,
reason=Authentication failed. Browser based integrations - to login append
'?login-form-required=y to the url you tried to access.}}
PS: adding the ?login-form-required=y to the URL, will bring up a log-in window when called in a browser, but not here. Appending the line to the URL actually still gives the same error message, and suggestion to append it again. Also, when called in a browser, the is-authenticated returns a 200, success, even without the login-form.
When you log in, you're getting a cookie which is a name plus a value.
The REST server expects you to pass this in the request header with every request you make.
Look into the object which you get for client.request(); there should be a way to specify additional headers to send to the server. The header name must be Cookie and the header value must be name=value.
So if the server responds with a cookie called sessionID with the value 1234, then you need something like:
client.request().header("Cookie", "sessionID=1234")
Related:
http://en.wikipedia.org/wiki/HTTP_cookie
Please tell me what is the better trick to be sure of a HttpClient response, for example, if we do a login through HttpClient and we need to tell the user of success or failure of his login operation.
Thank you in advance!
PS.: I don't need just to know response Http Status, I need to be sure that I am in the right page after response, example : login.php ==> home.php, if I post my request to login.php, how can I be sure that I am now in hom.php (login success) or I always stay in login.php (login failed)
HttpClient.execute() is going to return a HttpResponse
HttpResponse.getStatusLine().getStatusCode() will give you the HTTP response code as an int.
See:
http://developer.android.com/reference/org/apache/http/client/HttpClient.html
http://developer.android.com/reference/org/apache/http/HttpResponse.html
http://developer.android.com/reference/org/apache/http/StatusLine.html
Edit to add from comments below:
You're not using a web browser. The only way you're going to be "on another page" is if you received a 302 redirect and then sent a request for the other page. In which case ... you know which page you have.
If the PHP login script is utterly broken and just returns two different pages depending on whether you logged in or not, you're on your own. Parse the response and hope for the best. More than likely there's going to be a cookie or custom header in the response if that's the case, and you're going to have to look for it.
I am working on a program that will download a facebook page so I have the html. However, when I download it, I get the facebook page that isn't logged in.
Is there a way to somehow send my facebook login so facebook thinks the program is logged in, so I get the correct html?
If you want to get information from Facebook, you should be using the API available to you at https://developers.facebook.com/docs/
. The API provides access to most data that you would want, and it does so with OAuth authentication and JSON responses, which both have a lot of support in the development community (you will be able to find several libraries to handle these types of data without having to code it yourself). There are also samples, SDKs for a number of different programming language, and lots of good information.
Otherwise, if you want the HTML specifically, you can use the components at http://hc.apache.org/httpcomponents-client-ga/index.html
. This is some code that you can use to get a HTTP page...
HttpGet request = new HttpGet("http://www.facebook.com");
// Send the request
DefaultHttpClient client = new DefaultHttpClient();
HttpResponse response = client.execute(request);
// Get the response code
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
// Success
String responseMessage = EntityUtils.toString(response.getEntity());
// do something with the response here
}
If you need to send data, such as sending the login information to Facebook, you can use HttpPost instead of HttpGet, and attach your login information.
You should be warned, however, that Facebook is pretty strict at banning people that use HTTP requests rather than their API, so I would discourage you away from doing this. I direct you to the Facebook Platform Policy here... https://developers.facebook.com/policy/
You should look at the Facebook API: https://developers.facebook.com/
I have been using HTTPClient version 4.1.2 to try to access a REST over HTTP API that requires Basic Authentication. Here is client code:
DefaultHttpClient httpClient = new DefaultHttpClient(new ThreadSafeClientConnManager());
// Enable HTTP Basic Auth
httpClient.getCredentialsProvider().setCredentials(
new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT),
new UsernamePasswordCredentials(this.username, this.password));
HttpHost proxy = new HttpHost(this.proxyURI.getHost(), this.proxyURI.getPort());
httpClient.getParams().setParameter(ConnRouteParams.DEFAULT_PROXY, proxy);
When I construct a POST request, like this:
HttpPost request = new HttpPost("http://my/url");
request.addHeader(new BasicHeader("Content-type", "application/atom+xml; type=entry")); // required by vendor
request.setEntity(new StringEntity("My content"));
HttpResponse response = client.execute(request);
I see in Charles Proxy that there are two requests being sent. One without the Authorization: Basic ... header and one with it. The first one fails with a 401, as you would expect, but the second goes through just fine with a 201.
Does anyone know why this happens? Thanks!
EDIT:
I should make clear that I have already looked at this question, but as you can see I set the AuthScope the same way and it didn't solve my problem. Also, I am creating a new HttpClient every time I made a request (though I use the same ConnectionManager), but even if I use the same HttpClient for multiple requests, the problem still persists.
EDIT 2:
So it looks like what #LastCoder was suggesting is the way to do. See this answer to another question. The problem stems from my lack of knowledge around the HTTP spec. What I'm looking to do is called "preemptive authentication" and the HttpClient docs mention it here. Thankfully, the answer linked to above is a much shorter and cleaner way to do it.
Rather than using .setCredentials() why don't you just encode USERNAME:PASSWORD and add the authentication header with .addHeader()
This means that your server/target endpoint is creating a new session for every client request. This forces every request of yours to go through a hand-shake, which means the clients first makes the call and realizes that it needs authorization, then it follows with the authorization. What you need to do is send the authorization preemptively as follows:
httpClient.getParams().setAuthenticationPreemptive(true);
Just to understand the process you may log your client request headers, to give you an idea of what your client is sending and receiving:
See if this works.