Getting token from the URL in Java - java

In my project requirement, I was given a URL http://abc.grp.auth where it is accessible only in abc network. Am hitting this URL from browser and able to view the token in below format.
{"token" : "eqwqkldsdkldflanflna$%$!##"}
I want to get this token in java code within abc network as below.
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
But this code is giving 401 exception. This URL is taking the windows login, validating and sending the token. How can I achieve this in Java.
Thanks in Advance.

If there is used some kind of Basic authentication you can try to set special request header. Like this:
HttpGet httpget = new HttpGet(uri);
String encoding = Base64.encode(usr + ":" + psw);
httpget.setHeader("Authorization", "Basic " + encoding);

Related

How to create a cookie and use it in HttpURLConnection?

I have the following python code which creates a cookie and adds it to the session. What would be the equivalent java code for it using HttpURLConnection? I basically want to do a HTTP POST request using the generated cookie.
session = requests.session()
session.auth = (username, password)
try:
token = session.get(SITEMINDER_URL % server, verify=False)
session.cookies.update(dict(SMSESSION=json.loads(token.content)['SMSESSION']))
except Exception as ex:
raise Exception("Failed in authenticating with siteminder", ex)
response = session.post(api_url, headers=headers, verify=False, json=data)
You would use something like this:
HttpURLConnection httpconn = < some source to get a HttpURLConnection >;
String cookieName = "SMSESSION"; // note this is the default but SM can use other prefixes
String cookieValue = < your token content >;
httpurl.setRequestProperty("Cookie", cookieName + "=" + cookieValue);
Also, from the javadocs: NOTE: HTTP requires all request properties which can legally have multiple instances with the same key to use a comma-separated list syntax which enables multiple properties to be appended into a single property
Which leads me to pointing out that using the HttpUrlConnection directly is really clumsy. I recommend you look at an HTTP client library such as Apache HTTP Client http://hc.apache.org/httpcomponents-client-ga/
In my opinion, you can just create an HttpUrlConnection object assigning a List of Cookies as follows:
List<String> cookies = new ArrayList<>();
//Or using a map With entries: Key and value for each cookie
cookies.add("User-Agent=MyUserAgent"); //etc...
URL site = new URL("https://myurl.com");
HttpsURLConnection conn = (HttpsURLConnection) site.openConnection();
for (String string: cookies) {
conn.setRequestProperty("Cookie", string);
}
However this is the simplest but not the best way to do so.
To get higher abstraction for Cookie use CookieManager and CookieStore classes. Here is an example:
HttpURLConnection connection
CookieManager cookieManager = new CookieManager();
HttpCookie cookie = new HttpCookie("cookieName","cookieValue");
cookieManager.getCookieStore().add(null,cookie);
connection.setRequestProperty("Cookie", String.join( ";", cookieManager.getCookieStore().getCookies()));
Try This:
URL url = new URL("http://www.example.com");
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setRequestProperty("Cookie", "name1=value1; name2=value2");
conn.connect();

Authentication requests using HTTPS to an API in Java

I am looking to use an API called HookTheory. I am making the HTTPS calls in Java, and since its my first time using HTTP or HTTPS clients I am running into a few road blocks.
Here are the document's details on User Authentication:
You authenticate to the Hooktheory API by providing an HTTP Bearer Token, according to the OAuth 2 protocol. Your HTTP Bearer Token is retrieved through the API with your www.hooktheory.com username and password. To retrieve your HTTP Bearer Token, make the following request:
POST users/auth
The body of the request must contain your www.hooktheory.com username and password:
{
"username": "Hooktheory",
"password": "0123456789"
}
The response will contain three fields, as shown below:
{
"id": 1234,
"username": "Hooktheory",
"activkey": "aoa6jjacz34kcta3aomeqwuz89"
}
The "activkey" property contains your HTTP Bearer Token; include it as an authorization header in all future requests to the API.
Can someone explain in better detail how I would go about doing this in Java?
My starter code is the following:
String url = "https://api.hooktheory.com/v1/users/auth";
URL obj = new URL(url);
HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
//add request header
con.setRequestMethod("POST");
con.setRequestProperty("username", username);
con.setRequestProperty("password", password);
String urlParameters = "sn=C02G8416DRJM&cn=&locale=&caller=&num=12345";
// Send post request
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(urlParameters);
wr.flush();
wr.close();
int responseCode = con.getResponseCode();
System.out.println("\nSending 'POST' request to URL : " + url);
System.out.println("Post parameters : " + urlParameters);
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();
//print result
System.out.println(response.toString());
This code is basically a copy of the code here.
I get a 401 error (authentication) when I run the post code above. I'm guessing its because I haven't formatted the get/post requests correctly.
Can somebody point me in the right direction?
You've set username and password as request properties, which are HTTP headers. Per the HookTheory docs, you need to send these on the request body.
Specifically, you need to send the JSON request on the body like this:
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
String requestBody = String.format("{ \"username\": \"%s\", \"password\": \"%s\" }", username, password);
wr.writeBytes(requestBody);
Also, per their docs you should indicate that this is JSON by setting the Accept and Content-Type headers. This is done prior to sending the post request data through calls like this:
con.setRequestProperty("Accept", "application/json");
con.setRequestProperty("Content-Type", "application/json");
So the entire block looks like:
String url = "https://api.hooktheory.com/v1/users/auth";
URL obj = new URL(url);
HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Accept", "application/json");
con.setRequestProperty("Content-Type", "application/json");
// Send post request
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
String requestBody = String.format("{ \"username\": \"%s\", \"password\": \"%s\" }", username, password);
wr.writeBytes(requestBody);
wr.flush();
wr.close();
code 401 clearly specifies something wrong with authentication. stack trace shows unauthenticated on server side.
10.4.2 401 Unauthorized
The request requires user authentication. The response MUST include a WWW-Authenticate header field (section 14.47) containing a challenge applicable to the requested resource. The client MAY repeat the request with a suitable Authorization header field (section 14.8). If the request already included Authorization credentials, then the 401 response indicates that authorization has been refused for those credentials. If the 401 response contains the same challenge as the prior response, and the user agent has already attempted authentication at least once, then the user SHOULD be presented the entity that was given in the response, since that entity might include relevant diagnostic information. HTTP access authentication is explained in "HTTP Authentication: Basic and Digest Access Authentication"

getting filenotfoundexception while sending json data using java

I am trying to send json data to Influx db using following code:
String url = "http://xx.x.xx.xx:8086/db/monitoring/check_1113?u=root&p=root";
URL obj = new URL(url);
HttpURLConnection conn = (HttpURLConnection) obj.openConnection();
conn.setRequestProperty("Content-Type", "application/json");
conn.setDoOutput(true);
conn.setRequestMethod("PUT");
//String userpass = "user" + ":" + "pass";
//String basicAuth = "Basic " + javax.xml.bind.DatatypeConverter.printBase64Binary(userpass.getBytes("UTF-8"));
//conn.setRequestProperty ("Authorization", basicAuth);
//String data = "{\"format\":\"json\",\"pattern\":\"#\"}";
System.out.println("Data to send: "+"[{\"name\": \"check_222\",\"columns\": [\"time\", \"sequence_number\", \"value\"],\"points\": [["+unixTime+", 1, \"122\"]]}]");
String data = "[{\"name\": \"check_333\",\"columns\": [\"time\", \"sequence_number\", \"value\"],\"points\": [["+14444444444+", 1, \"122\"]]}]";
OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream());
out.write(data);
out.close();
new InputStreamReader(conn.getInputStream());
System.out.println("Data Sent");
Where xx.xx.xx.xx is the ip of server where influx is deployed and i am using the Ip.
When i do a manual curl with this data (on localhost), the data is sent successfully. curl is provided below:
curl -X POST -d '[{"name": "check_223","columns": ["time", "sequence_number", "value"],"points": [[1445271004000,1,70.8880519867]]}]' 'http://localhost:8086/db/monitoring/series?u=root&p=root'
But when I run the code to send the data via the java program shared above, i get following error:
java.io.FileNotFoundException: http://xx.x.xx.xx:8086/db/monitoring/check_1113?u=root&p=root
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1834)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1439)
at com.snapdeal.hadoop.monitoring.hdfs1.App.sendJsonDataToInflux(App.java:52)
at com.snapdeal.hadoop.monitoring.hdfs1.App.main(App.java:89)
[INFO - 2015-10-20T16:27:13.152Z] ShutdownReqHand - _handle - About to shutdown
And to add to it, I am using phantomJS to get the data from web page and pass that data in the JSON request. But for simplicity I have hard-coded it at present.
This should be relatively obvious. A 405 indicates that the HTTP Method on the request is not supported by the endpoint. The service you are calling does not support a PUT method.

Apache HttpClient HttpGet url with colon

I am trying to issue a get with a colon in one of my parameters but it fails with an unknownHostException here is my code:
String id = "{\"ID\":\"John Doe\"}";
String encodedID = URLEncoder.encode(id, "UTF-8").replace("+", "%20");
endpoint="https://127.0.0.1/getResourceNameToUse?id=" + encodedID;
HttpResponse response = new HttpResponse();
HttpGet httpget = new HttpGet(endpoint);
response = httpclient.execute(httpget, new RESTResponseHandler());
I get the following error:
java.net.UnknownHostException: 127.0.0.1/getResourceNameToUse?id={"ID"
So it would seem that the colon is breaking the get request. Is there a way to fix this? Why is encoding it not fixing the problem? My encoded id looks like this:
%7B%22ID%22%3A%22John%20Doe%22%7D
When I run an approximation of your code, your resulting URL is:
https://127.0.0.0/getResourceNameToUse?id=%7B%22ID%22%3A%22John%20Doe%22%7D
This is an absolutely valid URL as far as I can see. I don't see any : characters in it that would confuse the HttpClient. Let's look at the exception:
java.net.UnknownHostException: 127.0.0.0/getResourceNameToUse?id={"ID"
It looks to me that something is not using your encoded URL since it shows the {"ID as opposed to %7B%22ID%22. Any chance your code in your post isn't exactly the code you were running?
I also notice that you are going to the IP 127.0.0.0. Any chance you wanted 127.0.0.1 to connect to localhost?
I was able to fix it by essentially double url encoding the colon:
String id = "{\"ID\":\"John Doe\"}";
id = id.replace(":","%3A");
String encodedID = URLEncoder.encode(id, "UTF-8").replace("+", "%20");
endpoint="https://127.0.0.1/getResourceNameToUse?id=" + encodedID;
HttpResponse response = new HttpResponse();
HttpGet httpget = new HttpGet(endpoint);
response = httpclient.execute(httpget, new RESTResponseHandler());

HttpURLConnection sends a POST request even though httpCon.setRequestMethod("GET"); is set

Here is my code:
String addr = "http://172.26.41.18:8080/domain/list";
URL url = new URL(addr);
HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
httpCon.setDoOutput(true);
httpCon.setDoInput(true);
httpCon.setUseCaches(false);
httpCon.setAllowUserInteraction(false);
httpCon.setRequestMethod("GET");
httpCon.addRequestProperty("Authorization", "Basic YWRtaW4fYFgjkl5463");
httpCon.connect();
OutputStreamWriter out = new OutputStreamWriter(httpCon.getOutputStream());
System.out.println(httpCon.getResponseCode());
System.out.println(httpCon.getResponseMessage());
out.close();
What I see in response:
500 Server error
I open my httpCon var, and what I see:
POST /rest/platform/domain/list HTTP/1.1
Why is it set to POST even though I have used httpCon.setRequestMethod("GET"); to set it to GET?
The httpCon.setDoOutput(true); implicitly set the request method to POST because that's the default method whenever you want to send a request body.
If you want to use GET, remove that line and remove the OutputStreamWriter out = new OutputStreamWriter(httpCon.getOutputStream()); line. You don't need to send a request body for GET requests.
The following should do for a simple GET request:
String addr = "http://172.26.41.18:8080/domain/list";
URL url = new URL(addr);
HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
httpCon.setUseCaches(false);
httpCon.setAllowUserInteraction(false);
httpCon.addRequestProperty("Authorization", "Basic YWRtaW4fYFgjkl5463");
System.out.println(httpCon.getResponseCode());
System.out.println(httpCon.getResponseMessage());
See also:
Using java.net.URLConnection to fire and handle HTTP requests
Unrelated to the concrete problem, the password part of your Authorization header value doesn't seem to be properly Base64-encoded. Perhaps it's scrambled because it was examplary, but even if it wasn't I'd fix your Base64 encoding approach.

Categories