Can someone please explain how exactly the user credentials are passed to the server in the below code...
URL urlObj = new URL("https://javaguy.com");
HttpURLConnection conn = (HttpURLConnection) urlObj.openConnection(); conn.setRequestMethod("GET");
conn.setRequestProperty("Accept", "text/xml");
String userPassword = username + ":" + password;
byte[] authEncBytes = Base64.encodeBase64(userPassword.getBytes());
String authStringEnc = new String(authEncBytes);
conn.setRequestProperty("Authorization", "Basic " + authStringEnc);
Is it part of the HTTP header? Just curious.
Thanks in advance.
You've answered your own question, but yes. The "Authorization" is part of the header.
You can read more about basic authentication on the wikipedia.
Then the javadoc isn't super clear, but the setRequestProperty should add the new property to the request header.
As a side note, I would urge you to consider using a library like HttpClient if you're planning on doing any http requests in a production system. Working directly with URL and URLConnection directly can be tricky. HttpClient isn't super easy to work with either, but it is easier then URL/URLConnection.
There are two HttpClient libraries, make sure you're working with version 4 (which is the latest version at the time of this post) and not version 3.
Related
I am attempting to authenticate from the android app. It is an apache basic auth. It seems, through error logs, that the webpage is taking what is after the URL as the username for some reason? Any thoughts on this? Here is my code:
URL url = new URL("https://website.com/");
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setSSLSocketFactory(context.getSocketFactory());
connection.setRequestProperty("Authorization", "Basic " +
Base64.encode("user:pass".getBytes(), Base64.NO_WRAP));
connection.setDoOutput(true);
connection.connect();
If i add a path the the website, it tells me that that path is not a user. Without a path it says that "/" is not a user.
I have also tried doing user:pass#website.com which didn't work either.
I am having trouble getting a 401 unauthorized response from the server,I am doing a "GET" call from a ruby on rails api the oauth token is in the header like this.
urlConnection = (HttpURLConnection) url.openConnection();
OAuth = "bearer " + Base64.encodeToString(userpass.getBytes(), Base64.NO_WRAP);
Log.e("auth", oAuth_token);
urlConnection.setRequestMethod("GET");
urlConnection.setRequestProperty("Authorization", OAuth);
urlConnection.setRequestProperty("Content-Type", "application/json");
urlConnection.setRequestProperty("Accept", "application/json");
urlConnection.connect();
Userpass is the actual token.
This works in postman as well as on iOS but android is getting a 401
The Bearer Token Usage specification (RFC 6750) is a bit confusing. You don't have to base64-encode the access token before use. To be concrete, your code should be simply like this:
OAuth = "Bearer " + userpass;
See this discussion where the questioner confessed he had had the same confusion as yours.
I made an app. for Android which uses the C2DM service from Google. I
made a server simulator from some tutorials and it works fine. My
problem is, I tried to build a Java Servlet. From the Android device
it receives fine the message and saves the Registration ID, but when I
try to send a https POST request to the Google C2DM Server it always
gets a SocketTimeoutException : Timeout while fetching:
https://android.clients.google.com/c2dm/send.
I don't get why this is happening when the same works on the Android
device. Here is the code:
//The AuthToken from Google Client Login
String auth_key = TOKEN;
StringBuilder postDataBuilder = new StringBuilder();
//some parameters to pass, I've checked and it's correct, it's working
//with Fiddler
postDataBuilder.append(PARAM_REGISTRATION_ID).append("=").append(REGISTRATION_ID);
postDataBuilder.append("&").append(PARAM_COLLAPSE_KEY).append("=").append("0");
postDataBuilder.append("&").append("data.payload").append("=").append(URLEncoder.encode(message, UTF8));
byte[] postData = postDataBuilder.toString().getBytes(UTF8);
URL url = new URL("https://android.clients.google.com/c2dm/send");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type","application/x-www-form-urlencoded;charset=UTF-8");
conn.setRequestProperty("Content-Length",Integer.toString(postData.length));
conn.setRequestProperty("Authorization", "GoogleLogin auth="+auth_key);
OutputStream out = conn.getOutputStream();
out.write(postData);
out.close();
int responseCode = conn.getResponseCode();
//here comes the error processing, but I can't reach it, because of
//the exception.
if (responseCode == 401 || responseCode == 403) {
//....
}
Thanks for your help :).
The first obvious thing to check is - if you have thought of this I apologise - are you behind a proxy server e.g. a company firewall? If so a timeout is exactly the symptom I'd expect with the above code. (This catches me out all the time!)
With the latter half of your code (from the HttpURLConnection declaration on), unmodified, I see a timeout; on my system (behind a company firewall), with two changes I get a 200 OK back:
addition of a proxy object passed to the HttpUrlConnection factory as follows:
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("...", 8080));
HttpURLConnection conn = (HttpURLConnection) url.openConnection(proxy);
accepting the C2DM server's certificate that wasn't trusted by my JVM. For test purposes I overrode the default hostname verifier and TrustManager as described in Trusting all certificates using HttpClient over HTTPS . For production you should look at a more secure solution.
Another thing I spotted; it doesn't seem to matter but http://code.google.com/android/c2dm/index.html#push says to post to https://android.apis.google.com/c2dm/send, not android.clients.google.com - just something to be aware of that might break in future.
I faced same problem and
I had tried :
URL url = new URL("http://android.apis.google.com/c2dm/send");
instead of :
URL url = new URL("https://android.apis.google.com/c2dm/send");
it worked for me.
I was trying to get a certain page through java, but with this page I didn't succeed.
Now in my browser it does work, but when I disable Cookies in the settings, it doesn't anymore.
So I probably need to add cookies to my post request in java.
So I went searching the interwebs, but unfortunately I couldn't really find anything useful. mostly it was vague, scattered or irrelevant.
So now my question :
Could anyone show me how to do it (mentioned above^^), or point me to a clear site?
Here's a simple example of setting a cookie in a POST request with URLConnection:
URL url = new URL("http://example.com/");
String postData = "foo bar baz";
URLConnection con = url.openConnection();
con.setDoOutput(true);
con.setRequestProperty("Cookie", "name=value");
con.setRequestProperty("Content-Type", "text/plain; charset=utf-8");
con.connect();
OutputStreamWriter out = new OutputStreamWriter(con.getOutputStream(), "UTF-8");
out.write(postData);
out.close();
You probably need to pass a cookie from a previous request, see this answer for an example. Also consider using Apache HttpClient to make things easier.
URL url = new URL("http://hostname:80");
URLConnection conn = url.openConnection();
conn.setRequestProperty("Cookie", "name1=value1; name2=value2");
conn.connect();
My java snippet looks like:
...
String type = "text/plain;charset=UTF-8";
URL url = new URL("http://xxx/");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("OPTIONS");
conn.setRequestProperty("Content-Type", type);
...
When I sniff what this sends it sends a
OPTIONS / HTTP/1.1
which appears to be the default.
However, I actually want to send
OPTIONS * HTTP/1.0
How would I do this?
You can't do that with "plain" java.net.URLConnection. Consider replacing by Apache Commons HttpClient which is less bloated and more configureable. You can force HTTP 1.0 mode by setting http.protocol.version to HttpVersion.HTTP_1_0 in HttpClient#getParams(). You can find an example in this document.
I agree with the answer the following is the code using HTTPClient
HttpClient client = new DefaultHttpClient();
client.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_0);
Hope it helps some one..