I'm receiving the following SSLHandshakeException when trying to send a push notification through the C2DM servers.
javax.net.ssl.SSLHandshakeException: Could not verify SSL certificate for: https://android.apis.google.com/c2dm/send
The code to send the message is as follows, and is running on App Engine. Everything works fine when I use cURL, so I know that the server authentication code and device registration ID are correct.
public static void sendHttpPostToC2dmService(String msg, PrintWriter out) {
String authCode = "XXXX";
String regID = "YYYY";
try {
URL url = new URL("https://android.apis.google.com/c2dm/send");
String data = URLEncoder.encode("registration_id", "UTF-8") + "="
+ URLEncoder.encode(regID, "UTF-8");
data += "&"
+ URLEncoder.encode("Authorization: GoogleLogin auth",
"UTF-8") + "="
+ URLEncoder.encode(authCode, "UTF-8");
data += "&" + URLEncoder.encode("collapse_key", "UTF-8") + "="
+ URLEncoder.encode("something", "UTF-8");
data += "&" + URLEncoder.encode("data.message", "UTF-8") + "="
+ URLEncoder.encode(msg, "UTF-8");
out.println("data=" + data);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
OutputStreamWriter writer = new OutputStreamWriter(
connection.getOutputStream());
writer.write(data);
writer.close();
out.println("responseCode=" + connection.getResponseCode());
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
String responseLine = new BufferedReader(new InputStreamReader(
connection.getInputStream())).readLine();
out.println("responseLine=" + responseLine);
} else {
// Server returned HTTP error code.
}
} catch (MalformedURLException e) {
out.println("MalformedURL");
out.println(e.getMessage());
} catch (IOException e) {
out.println("IOException");
out.println(e.getMessage());
e.printStackTrace(out);
}
}
It seems like others have also had this problem, but I haven't been able to find a clear solution (at least not one I'm able to understand). Appreciate any help.
You need to use HttpsURLConnection instead of HttpURLConnection.
AFAIK, HttpURLConnection doesn't verify hostnames.
If you are in the testing phase, you could use the non-secure url to push a notification.
http://android.apis.google.com/c2dm/send
I also got around this issue by adding a certificate validation callback to accept any certificate, but this was on a C# server. I'm sure there is a Java equivalent for this.
In production code you would want to verify the correct certificate or maybe just encrypt the data you are sending.
Related
I keep getting a "null" exception when I run this code. If I manually type the url string into my browser the php script posts "{query_result:SUCCESS}" indicating it worked, but when I try it via this code I just get the Exception e as "null". Can anyone help?
protected String signUp(String username) {
String link = "http://12.34.56.78/JSON_addUser.php";
String data = "";
BufferedReader bufferedReader;
String result = "";
String message;
try {
data += "?username=" + URLEncoder.encode(username, "UTF-8");
link += data;
URL url = new URL(link);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
bufferedReader = new BufferedReader(new InputStreamReader(con.getInputStream()));
result = bufferedReader.readLine();
return result;
} catch (Exception e) {
message = "Exception trying: " + link + " Got: " + e.getMessage() + result;
return message;
}
}
Pretty often servers block requests like this because they are automated without a "User Agent" header. You might want to behave like a "real" browser.
Also i see a content encoding issue here. The constructor from InputStreamReader uses the default encoding and this might not be the encoding from the server--it might crash from converting the bytes into chars.
I try to push notification from java server to IOS client
and i have this error(response from codename one server)
{"error":"Failed to send push to APNS: com.notnoop.exceptions.NetworkIOException: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake"}
String GOOGLE_SERVER_KEY = "********************************************";
HttpsURLConnection connection;
String url = "https://push.codenameone.com/push/push";
String TOKEN = "******-****-*****-*****-**************";
String URL_ENCODED_LINK_TO_YOUR_P12_FILE =
"https://dl.dropboxusercontent.com/*/******************/Certificates.p12";
String URL_ENCODED_CERTIFICATE_PASSWORD = "******";
String deviceId =
"cn1-gcm-*******************************************************";
String deviceId2 =
"cn1-ios-***************************************************";
String MESSAGE_BODY = "This notification message coming from server";
try {
connection = (HttpsURLConnection)new URL(url).openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
String query =
"token=" + TOKEN + "&device=" + deviceId + "&device=" +
deviceId2 + "&type=1&auth=" + GOOGLE_SERVER_KEY +
"&certPassword=" + URL_ENCODED_CERTIFICATE_PASSWORD +
"&cert=" + URL_ENCODED_LINK_TO_YOUR_P12_FILE + "&body=" +
URLEncoder.encode(MESSAGE_BODY, "UTF-8") + "&production=false";
try {
OutputStream output = connection.getOutputStream();
output.write(query.getBytes("UTF-8"));
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("ResponseCode : " + connection.getResponseCode());
System.out.println("ResponsenMessage : " +
connection.getResponseMessage());
BufferedReader br =new BufferedReader(new InputStreamReader((connection.getInputStream())));
String output;
String result = "";
System.out.println("Output .... \n");
while ((output = br.readLine()) != null) {
System.out.println(output);
result += output + "\n";
}
connection.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
Output from codename one Server
Response Code : 200
Response Message : OK
Output ....
{"error":"Failed to send push to APNS: com.notnoop.exceptions.NetworkIOException: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake"}
A handshake exception would generally mean the Codename One servers failed to connect due to a security issue. This probably means your P12 is incorrect.
Are you sure you used the right P12 file? Keep in mind that there are 2 push certificates (not to be confused with the 2 signing certificates) and only one of them should be used based on the value of the sandbox flag.
Did you use the certificate wizard?
I think 2195 and 2196 ports are disabled on either the server or client side which needs to be enabled for apple push notification.
I'm working on a program that queries Google Safe Browsing for certain urls, but I'm getting an error that I don't think I should be getting.
I'm sending the following request:
2
http://google.com
http://facebook.com
via POST to: https://sb-ssl.google.com/safebrowsing/api/lookup?client=api&apikey=[KEY]&appver=1.5.2&pver=3.1
However, I'm getting a 403 response.
This is what the documentation says for HTTP POST lookup errors:
The server generates the following HTTP error codes for the POST request:
•200: AT LEAST ONE of the queried URLs are matched in either the phishing, malware, or unwanted software lists. The actual results are returned through the response body.
•204: NONE of the queried URLs matched the phishing, malware, or unwanted software lists, and no response body is returned.
•400: Bad Request—The HTTP request was not correctly formed.
•401: Not Authorized—The API key is not authorized.
•503: Service Unavailable—The server cannot handle the request. Besides the normal server failures, this could also indicate that the client has been “throttled” for sending too many requests.
The response code 403 isn't listed, yet I'm getting it.
I have triple-checked my API-key and made sure the API is enabled for my project. I'm using a Server-key, but I also tried a Browser-key.
I tried doing a GET request also, and that did work, but I cannot get POST to work. What's going on?
Here is my code:
try {
String baseURL="https://sb-ssl.google.com/safebrowsing/api/lookup";
String arguments = "";
arguments +=URLEncoder.encode("client", "UTF-8") + "=" + URLEncoder.encode("api", "UTF-8") + "&";
arguments +=URLEncoder.encode("apikey", "UTF-8") + "=" + URLEncoder.encode("[KEY]", "UTF-8") + "&";
arguments +=URLEncoder.encode("appver", "UTF-8") + "=" + URLEncoder.encode("1.5.2", "UTF-8") + "&";
arguments +=URLEncoder.encode("pver", "UTF-8") + "=" + URLEncoder.encode("3.1", "UTF-8");
// Construct the url object representing cgi script
URL url = new URL(baseURL + "?" + arguments);
// Get a URLConnection object, to write to POST method
HttpURLConnection connect = (HttpURLConnection) url.openConnection();
connect.setRequestMethod("POST");
// Specify connection settings
connect.setDoInput(true);
connect.setDoOutput(true);
// Get an output stream for writing
OutputStream output = connect.getOutputStream();
PrintStream pout = new PrintStream (output);
pout.print("2");
pout.println();
pout.print("http://www.google.com");
pout.println();
pout.print("http://www.facebook.com");
pout.close();
BufferedReader in = new BufferedReader(new InputStreamReader(connect.getInputStream()));
String decodedString;
while ((decodedString = in.readLine()) != null) {
System.out.println("w: " + decodedString);
}
in.close();
} catch(Exception e) {
e.printStackTrace();
}
I found the error. The CGI parameter was incorrect. It should have been key and not apikey. Still weird that you get an undocumented response-code though.
I made a andoid application in which I am getting response from php server, requesting in POST format. I am using below code for http connection:
// random string as boundary for multi-part http post
String strBoundary = "3i2ndDfv2rTHiSisAbouNdArYfORhtTPEefj3q2f";
String endLine = "\r\n";
OutputStream os;
String url = encodeUrl(methodType, graphURL, params);
Log.d("url - ",url);
Log.d("Method Type - ", methodType + " URL - " + url);
HttpURLConnection conn = (HttpURLConnection) new URL(url)
.openConnection();
conn.setConnectTimeout(60000);
conn.setReadTimeout(30000);
conn.setRequestProperty("User-Agent", System.getProperties()
.getProperty("http.agent"));
if (!methodType.equals("GET")) {
Bundle dataparams = new Bundle();
for (String key : params.keySet()) {
if (params.getByteArray(key) != null) {
dataparams.putByteArray(key, params.getByteArray(key));
}
}
// use method override
if (!params.containsKey("method")) {
params.putString("method", methodType);
}
if (params.containsKey("access_token")) {
#SuppressWarnings("deprecation")
String decoded_token = URLDecoder.decode(params
.getString("access_token"));
params.putString("access_token", decoded_token);
}
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type",
"multipart/form-data;boundary=" + strBoundary);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestProperty("Connection", "Keep-Alive");
conn.connect();
os = new BufferedOutputStream(conn.getOutputStream());
os.write(("--" + strBoundary + endLine).getBytes());
os.write((encodePostBody(params, strBoundary)).getBytes());
os.write((endLine + "--" + strBoundary + endLine).getBytes());
if (!dataparams.isEmpty()) {
for (String key : dataparams.keySet()) {
os.write(("Content-Disposition: form-data; filename=\""
+ key + "\"" + endLine).getBytes());
os
.write(("Content-Type: content/unknown" + endLine + endLine)
.getBytes());
os.write(dataparams.getByteArray(key));
os.write((endLine + "--" + strBoundary + endLine)
.getBytes());
}
}
os.flush();
}
String response = "";
try {
response = parseXmlSvn(conn.getInputStream());
} catch (FileNotFoundException e) {
// Error Stream contains JSON that we can parse to a FB error
//response = read(conn.getErrorStream());
Log.i("RESPONSE",""+response);
}
Log.i("RESPONSE", ""+response);
return response;
Everything is working fine on my demo server, I uploaded my PHP service to clients server. I am getting proper response from his server also.
But when client access app in 3G or 4G in some other country in his android devices, he is getting Blank response while the same service of same server can be accessible in iOS code easily by him. Is it some packet loss while getting response or any other problem?
I would really appreciate any help you can give me.
Thanks
I am trying to send HTTPS Post Request from jsp to Opera Server. But I can't. I have found many HTTP Post Request examples but no HTTPS. I am getting an Error Message now..
java.lang.ClassCastException: sun.net.www.protocol.https.HttpsURLConnectionImpl cannot be cast to com.sun.net.ssl.HttpsURLConnection
My import are as follows for this code
java.security.Security, com.sun.net.ssl.
My code as follows
try{
String data = URLEncoder.encode("AccountID", "UTF-8") + "=" + URLEncoder.encode(accountid, "UTF-8");
data += "&" + URLEncoder.encode("CallerTransactionID", "UTF-8") + "=" + URLEncoder.encode(callertransactionid, "UTF-8");
data += "&" + URLEncoder.encode("CurrentTime", "UTF-8") + "=" + URLEncoder.encode(currenttime, "UTF-8");
data += "&" + URLEncoder.encode("ErrorURL", "UTF-8") + "=" + URLEncoder.encode(errorurl, "UTF-8");
//data += "&" + URLEncoder.encode("FrameURL", "UTF-8") + "=" + URLEncoder.encode(frameurl, "UTF-8");
System.setProperty("java.protocol.handler.pkgs", "com.sun.net.ssl.internal.www.protocol");
java.security.Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
URL opxurl = new URL("https://opx-test.opera.com/opx/2.0/OPXPaymentEnable");
HttpsURLConnection connopx = (HttpsURLConnection) opxurl.openConnection();
connopx.setDoInput(true);
connopx.setDoOutput(true);
connopx.setRequestMethod("POST");
connopx.setFollowRedirects(true);
connopx.setRequestProperty("Content-length",String.valueOf(data.length()));
connopx.setRequestProperty("Content-Type","application/x-www- form-urlencoded");
// open up the output stream of the connection
DataOutputStream output = new DataOutputStream(connopx.getOutputStream());
// write out the data
int dataLength = data.length();
output.writeBytes(data);
//output.flush();
System.out.println("HOly Portal ResponseDesc Code:"+connopx.getResponseCode()+" : "+connopx.getResponseMessage());
// get ready to read the response from the cgi script
DataInputStream input = new DataInputStream( connopx.getInputStream() );
// read in each character until end-of-stream is detected
for( int c = input.read(); c != -1; c = input.read() )
System.out.print("HolyPortal respnse: "+ (char)c );
input.close();
After all connopx's settings you have to call
connopx.connect();
I use this import and it works in my code:
import javax.net.ssl.HttpsURLConnection;
I don't have the two lines above URL opxurl =
Have a look at this answer with similar issue also.
EDIT:
To avoid error 500 remove space in "application/x-www-form-urlencoded" and add those two lines right after output.writeBytes(data);:
output.flush();
output.close();
Then it should work.
This should be your code
try {
URL url = new URL("yourURL");
URLConnection conn = url.openConnection();
if (conn instanceof HttpsURLConnection) {
// Try again as HTTPS
HttpsURLConnection conn1 = (HttpsURLConnection) url.openConnection();
conn1.setHostnameVerifier(new HostnameVerifier() {
#Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
conn1.getResponseCode();
}
}
catch (MalformedURLException e) {
}
catch (IOException e) {
}