new to java - understanding an HTTP POST request - java

I have been trying to understand the postData() method in the following tutorial.
My understanding of the code is:
an nameValuePairs object, which contains some data is being sent over the internet to some web service located at this address: http://www.yoursite.com/script.php which will receive this nameValuePairs object

For example you want to send the age of a person to the webservice.
If you send data via GET the call of the webservice would be like this:
http://www.yoursite.com/script.php?age=18
If you send data via POST the call of the webservice would be like this:
http://www.yoursite.com/script.php
and the key-value arguments are integrated in the data stream of the request
So, to answer your question, no object will be sent,
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
nameValuePairs.add(new BasicNameValuePair("age", "18"));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
will integrate the key-value-list to the data stream of the request.

Yes, basically... server gets that name-value pair and can process it as it wants ...
For example when logging into your email account, you are sending two name-value pairs - username=your_username and password=your_password ... after receiving, server checks if username you sent is correct and if the password is valid for given username, and then sends you to your account or throws a message that data you supplied is invalid.
It is not java specific. It is http protocol, that can be implemented in any other language.

If you pass an id in like this,
nameValuePairs.add(new BasicNameValuePair("id", "20"));
In php page, you can get the value like this,
$id= $_POST['id'];

Related

How to make Java HttpPost NOT include url in body

We have some old java code that POSTs some fields and values to a dotnet5 web api - The api is having problems dealing with the body of the POST as it includes the url/uri as the first part of the body.
The Java sends: http://127.0.0.1:5555?producerRef=GREEN&systemId=78&status=false
But the api is expecting something like: producerRef=GREEN&systemId=78&status=false
as per https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST#example. If we send a test message via Postman then the api has no problems.
This is the Java code:
List<NameValuePair> params = new ArrayList<NameValuePair>(queryParams.size());
for (Map.Entry<String, String> entry : queryParams.entrySet()) {
params.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
}
// the address is just that, there's NO parameters
HttpPost post = new HttpPost(this.cmAddress.toURI());
post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
post.setHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded");
CloseableHttpResponse response = httpClient.execute(post);
It's quite simple, but always adds the url to the start of the body of the request. If this is the only way to produce this, what could I do to produce something that looks like this: https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST#example
Many Thanks.
This request seems like a GET request rather than a POST since the request params are in the URL. i don't know about the specifications of the Api you're using, but you can try OKHTTP, you can easily copy the code directly from postman
Postman Get example:
Your issue seems to be at below line
HttpPost post = new HttpPost(this.cmAddress.toURI());
This is the only place which will set the POST url ( another way is to use setURI which is not called anywhere in the code sample you have shared).
If you can use a debugger try checking the value of cmAdress variable

How to pass data in HTTP Header while redirecting a request in Java

is it possible to pass some data in HTTP Header, while redirecting a request from one server to another.
Here is my scenario,
I have one generic filter, via which every request is passing.
Now, based on some condition, I'm redirecting the request to some different server using the API objHttpServletResponse.sendRedirect(strURL).
But, the issue is, when I'm setting some data in response header like objHttpServletResponse.setHeader("Key", "Value"); That's not available in the redirected server.
So, my questions are,
1. Is there any way to pass some data in header while redirecting a request?
2. If not, what are the other possible ways to send some data while redirecting a request?
Please Note: few other ways, like
using URL parameters:
objHttpServletResponse.sendRedirect(strURL+"?param="+ strParamValue);
or
using session:
HttpSession session = httpRequest.getSession();
session.setAttribute("Key", "Value");
is not what I'm expecting.
The headers you set are written to the response that gets sent to the client, along with a Location header and a status code. See Redirecting a request using servlets and the "setHeader" method not working
The client is then supposed to send an identical request to the URL you specified in the Location header. Identical to the request it sent to you.
You want the browser to send a header you specify along with the redirected request. Have you considered adding a (domain) Cookie header? Some googling leads me to believe that cookies set in a redirect response will get picked up by most browsers. See http://blog.dubbelboer.com/2012/11/25/302-cookie.html
Please have a look at Apache HttpClient.
This example adds several parameters to the post request :
String url = "https://selfsolve.apple.com/wcResults.do";
HttpClient client = HttpClientBuilder.create().build();
HttpPost post = new HttpPost(url);
// add header
post.setHeader("User-Agent", USER_AGENT);
List<NameValuePair> urlParameters = new ArrayList<NameValuePair>();
urlParameters.add(new BasicNameValuePair("sn", "C02G8416DRJM"));
urlParameters.add(new BasicNameValuePair("cn", ""));
urlParameters.add(new BasicNameValuePair("locale", ""));
urlParameters.add(new BasicNameValuePair("caller", ""));
urlParameters.add(new BasicNameValuePair("num", "12345"));
post.setEntity(new UrlEncodedFormEntity(urlParameters));
HttpResponse response = client.execute(post);
System.out.println("Response Code : "
+ response.getStatusLine().getStatusCode());
The problem is that the redirect() method of the response initiates a new request altogether, thereby loosing the attributes that were set before redirecting. Luckily there is a fluent way of solving the problem still.
response.setHeader("Key", "Value");
request.getRequestDispatcher("redirecturl").forward(request, response);
Then in your destination you can do
response.getHeaders("key")
You can use JS redirect, i.e. instead of calling sendRedirect return HTML page with embedded javascript that will do redirect setting headers you need.
However, using GET parameters is really the best solution. If you have concerns about users altering parameters manually - use MAC code to protect parameters.See
Message authentication code
In simplest form, ?p1=1&p2=2&mac={mac value}, where {mac value} = md5('MY_SECRET_KEY' + 'p1=1&p2=2').
Receiving side can recalculate MAC and compare it with provided one. Since external users can not know 'MY_SECRET_KEY', they will not be able to make valid MAC.
Have you checked the HTTP request/response from/to server? You can use a number of plugins on chrome or firefox to check that. You would be able to see if value is being passed from your server to another server or not
Also retrieve the header using httpResponse.getHeader("Key"); not using request.getHeader("key"). One of my colleague was facing same issue some days back, he was using request to fetch header values

Box API Updating Email Alias Issue

I am trying to update email alias for different users. I am able to authenticate, get the code and then get the access token. I am sending the access token in the HTTP POST request as a Header. I am using Java & Apache HTTPClient to make the RESTful call. Here is the code snippet (Only relevant code shown).
if (httpClient != null) {
String apiURL = getApiURL();
apiURL = MessageFormat.format(apiURL, "firstname.lastname#company.com");
// apiURL = https://api.box.com/2.0/users/firstname.lastname#company.com/email_aliases
// firstname.lastname#company.com does exist in the Box Account
HttpPost post = new HttpPost(apiURL);
post.addHeader("Authorization", "Bearer "+accessToken);
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("email", "updateemail#company.com"));
post.setEntity(new UrlEncodedFormEntity(nameValuePairs, Charset.defaultCharset()));
HttpEntity entity = post.getEntity();
ResponseHandler<String> responseHandler = new BasicResponseHandler();
String responseFromBox = httpClient.execute(post, responseHandler);
writeResponse(response, responseFromBox);
if (responseFromBox != null) {
if (logger.isDebugEnabled()) {
logger.debug("apiURL-->"+apiURL);
logger.debug(responseFromBox);
}
}
}
The problem is that the response I get is some HTML code that says "The page you were viewing has expired. Please go back and try your request again." I was expecting some JSON string.
What I am doing incorrect? In the Post request instead of sending the email address I used the user id. But I get the same error.
In fact when I try to fetch the email alias of a user using the HTTP GET request I get an error "Not Found". The user does exist. I have an admin control. I can see them.
Thanks
Raj
Try a get on /users to get the array of all your users in the enterprise first. Is that working for you? If not, can you do a get on /users/me? If you can't get the former, then your API key may not have the "manage an enterprise" grant setup for it. You have to set that up in the app management, where you setup your OAuth2 callback URL.
Not sure why you are getting HTML back. That usually only happens on badly formed requests that our servers can't even parse, like you are hitting the wrong URL.
Just a reminder, OAuth2 URL is different from the API URL. 1st is https://www.box.com/api/oauth2/.... 2nd is https://api.box.com/2.0/...
As for setting the Email alias, that's entirely possible, once you know the ID of the user you are trying to set the alias for. Documentation is here
I was using the NameValuePair instead of the JSON string that was being expected. So I removed the following
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("email", "updateemail#company.com"));
post.setEntity(new UrlEncodedFormEntity(nameValuePairs, Charset.defaultCharset()));
and added
String json = "{\"email\":\"firstname.lastname#company.com\"}";
StringEntity entity = new StringEntity(json, Charset.defaultCharset());
post.setEntity(entity);
and then things started to work!

Encrypting Android app Data sent to MySQL DB

I have submitted an app to Amazon for approval, they came back with this:
"This app appears to be sending unencrypted, sensitive information. In this instance, the E-MAIL and PASSWORD, is being sent in clear text. Please update the app to encrypt all sensitive information."
On the server side, I encrypt the password in my database using the sha1() PHP method (pretty standard). I am assuming they want the password/email String that Java passes to be encrypted while in transit to the web service. I assume? If this is the case, I need to decrypt the data (specifically the email because this needs to be stored in my DB in plain text.
Has anyone seen this Amazon inquiry before? And is my explanation of it correct? And if so, is there a way in Java to temporary encrypt data while in transit?
Here is a sample in how I do it:
insertParam = new ArrayList<NameValuePair>();
insertParam.add(new BasicNameValuePair("Email", Email));
insertParam.add(new BasicNameValuePair("Password", Password));
insertParam.add(new BasicNameValuePair("Username", Username));
try {
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url_select);
httpPost.setEntity(new UrlEncodedFormEntity(insertParam));
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
is = httpEntity.getContent();
}
EDIT:
Looks like HTTPS is the way to go.
Amazon's requirement seems somewhat conservative, but could be best met by connecting to your web service via HTTPS instead of unencrypted HTTP. This is exactly what another StackOverflow user did in the end: Amazon AppStore Submission Failed: "Sensitive information like password is echoed in clear text without encryption"
While you could encrypt the data in your app, send it over the internet, and decrypt it on your server using a shared key, this is vulnerable to attackers that decompile your app to get the key.
Alternatively, you could generate a key pair, include the public key in the app and encrypt data with that, send it over the internet, and then use the private key on the server to decrypt the incoming data, but you're basically just re-implementing HTTPS manually.
At the end of the day, the "right" way to implement Amazon's requirement is to use HTTPS. Anything else is likely to be difficult to implement securely.

Trying to HttpPost a file in Android to my server

This is roughly the code I'm working with now:
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("json", json.toString()));
nameValuePairs.add(new BasicNameValuePair("blob", file.getAbsolutePath()));
post_request.setEntity(new UrlEncodedFormEntity(nameValuePairs));
The the reply I get back from the server is good for the first add() statement but, for the second one I'm not trying to send the path, I'm trying to send the file. Taking off .getAbsolutePath() should do the trick, but It won't let me as it only accepts strings. How would I go about sending the file?
you should use a MultipartEntity, not an UrlEncodedForm one. In a Multipart body you can store objects of different mime types

Categories

Resources