This is my Https client
public String sendHttpsRequest(String httpsUrl, HttpMethod method,
String body, Map<String, String> headers) {
String response = "";
int responseCode = 0;
HttpsURLConnection conn = null;
try {
URL url = new URL(httpsUrl);
conn = (HttpsURLConnection) url.openConnection();
conn.setRequestMethod(method.toString());
for (Map.Entry<String, String> entry : headers.entrySet()) {
conn.setRequestProperty(entry.getKey(), entry.getValue());
}
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setHostnameVerifier(new HostnameVerifier() {
#Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, new TrustManager[]{
new javax.net.ssl.X509TrustManager() {
#Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
#Override
public void checkServerTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
#Override
public void checkClientTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
}
}, null);
conn.setSSLSocketFactory(context.getSocketFactory());
String param = body;
DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
wr.writeBytes(param);
wr.flush();
wr.close();
responseCode = conn.getResponseCode();
InputStream in = conn.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line = "";
while ((line = reader.readLine()) != null) {
response += line;
}
reader.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
if(conn != null) {
conn.disconnect();
}
}
return responseCode == 200?response:Integer.toString(responseCode);
}
but for some reason it gives me a "405 Method not allowed" when I try to conncet to https://httpbin.org/get with following parameters.
TreeMap<String, String> map = new TreeMap<>();
map.put("Content-Type", "application/json");
System.out.println(new HttpLiveTest().sendHttpsRequest("https://httpbin.org/get" , HttpMethod.GET, "", map));
I also tried to connect to it through SoapUI with same parameters and it worked there.
I think the certificate that i'm using from Spring might be the problem but I wouldnt know how to solve that issue and why whould it answer with an 405?
Using Wireshark to look at the package didnt work because of TLS
Arnaud said: setDoOutput(true) may force the method to be POST
hes right.
user7236363 wrote:
java.net.ProtocolException: cannot write to a URLConnection if doOutput=false - call setDoOutput(true) is what im getting when i wont set it on true
he is also right.
Big picture:
What you want to do most of the time is a HTTP GET and that passes arguments in on the url - it doesnt requre any bytes to be written after the url so setting the Connection.setDoOutput(true) is not needed at all, hence dont do it when you want to do a GET.
Between the Connection.setRequestProperty(String Key, String Value) and the URL itself you should have everthing you need to make a properly formatted GET request.
I had a very simular problem and the root of it was me setting setDoOutput(true) and not realizing that it had a side effect that i didnt realize (ie setting the request method to post).
Related
I'm trying to get some data by the rest api of Jira. Thiw website is locally in my enterprise and on https. The first time we go on it we are automatically login by SSO. There are certificats too.
I have check all post about this error, try with User-Agent or TrustManager but nothing work :( then I can access to the page by my browser without any problem. It's work on two other computer and I didn't really understand why.
Error I got :
java.io.IOException: Server returned HTTP response code: 403 for URL: https://myjira.xx/rest/api/2/search?jql=project=PARE2+order+by+updated&fields=id,updated,summary,assignee,worklog&startAt=0&maxResults=30
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
And my code is :
public void connectToJira() throws Exception {
String adresse = "https://myjira.xx/";
adresse += "rest/api/2/search?jql=project=NAMEProject+order+by+updated&fields=id,updated,summary,assignee,worklog&startAt=0&maxResults=30";
TrustManager[] trustAllCerts = { new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
} };
try {
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {
}
URL url = new URL(adresse);
HttpURLConnection uc = (HttpURLConnection) url.openConnection();
uc.addRequestProperty("User-Agent", "Mozilla/5.0");
uc.setRequestProperty("Authorization", "Basic " + new String(Base64.getEncoder().encode("myUsername:myPassword".getBytes())));
if (401 == uc.getResponseCode()) {
throw new Exception("Code erreur 401");
}
StringBuilder sb = new StringBuilder();
BufferedReader reader = new BufferedReader(new InputStreamReader(uc.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
System.out.println(sb.toString());
}
I try to add certificats from my cacerts but same problem :(
Thanks
I have a java application that is making an HTTP DELETE to an external REST service. This error gets back to me from the server (running C#):
"Value cannot be null.\r\nParameter name: source\n at System.Linq.Enumerable.Count[TSource](IEnumerable`1 source)\r\n at AppCloud_Framework.Controllers.NotificationItemsController.DeleteNotificationItem(NotificationItem[] notificationItems) in C:\\Users\\jonas\\OneDrive\\VS Projects\\AppCloud Framework\\AppCloud Framework\\Controllers\\NotificationItemsController.cs:line 101\nValue:null"
The thing is, when I setup Postman to make the HTTP request to the same URL, with the same Payload and same HTTP method, the action is successful.
I do not have access to the server to investigate further so I need to find the resolution from the client side. Anyway it appears to be a client side issue.
I've been trying to find the problem myself but haven't succeeded. All I could come up with was to add "application/json" to Accept and Content-Type header properties.
My HTTP client:
public static Response execute(String url, Method method, String body) {
Response response = new Response();
try {
////////////////////////////////////////
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
} };
// Install the all-trusting trust manager
final SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
// Create all-trusting host name verifier
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
// Install the all-trusting host verifier
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
////////////////////////////////////////
URL urlObj = new URL(url);
HttpsURLConnection conn = (HttpsURLConnection) urlObj.openConnection();
conn.setInstanceFollowRedirects(false);
conn.setRequestMethod(method.toString());
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty("Accept", "application/json");
//conn.setRequestProperty("Authorization", _authToken);
if (method == Method.POST || method == Method.PUT || method == Method.DELETE) {
conn.setDoOutput(true);
final OutputStream os = conn.getOutputStream();
os.write(body.getBytes());
os.flush();
os.close();
}
int status = conn.getResponseCode();
//log.info("HTTP request status code: "+status);
InputStream is;
if (status>399){
is = conn.getErrorStream();
}else{
is = conn.getInputStream();
}
if (is==null) return null;
BufferedReader rd = new BufferedReader(new InputStreamReader(is,
"UTF-8"));
String line;
while ((line = rd.readLine()) != null) {
response.body += line;
}
rd.close();
response.statusCode = conn.getResponseCode();
conn.disconnect();
} catch (Exception e) {
//log.error(e.getMessage());
e.printStackTrace();
System.out.println("");
response.exception = e.getMessage();
}
return response;
}
I am making a request with this body(disregard the encoding issue, source of that is somewhere else):
[{"hash":"150a17e99f67ce29fcc600c92eee831d","instanceid":"cb440a6f-44ef-4f05-ab41-143153655b6e","text":"{\"C_FirstAndLastName\":\"und\",\"ContactID\":\"1374231\",\"C_Fax\":\"\"}","queueDate":"2016-10-04T03:18:37"},{"hash":"1a94d9b5acff1a27dfe45be4ca5d9138","instanceid":"fdsfdsf-44ef-4f05-ab41-143153655b6e","text":"{\"C_FirstAndLastName\":\"J?â??rgen\",\"ContactID\":\"323093\",\"C_Fax\":\"fsdfsd-B401-4AD3-AEA1-fdsfsdfsd\"}","queueDate":"2016-10-04T03:18:37"},{"hash":"8e592fb16d464bfd0f90f69818944198","instanceid":"fdsfsdf-44ef-4f05-ab41-143153655b6e","text":"{\"C_FirstAndLastName\":\"Claus\",\"ContactID\":\"2495844\",\"C_Fax\":\"fdsfsdgsd-304D-4E91-8586-fsdfsdfsd\"}","queueDate":"2016-10-04T03:18:37"},{"hash":"d6d226255e62690e50abbfa15c4b5462","instanceid":"cb440a6f-44ef-4f05-ab41-143153655b6e","text":"{\"C_FirstAndLastName\":\"Test J??rgen\",\"ContactID\":\"323093\",\"C_Fax\":\"fdsfsdfsd-B401-4AD3-AEA1-fdsfsdfsdf\"}","queueDate":"2016-10-04T03:18:49"}]
All I had to do was to define encoding in the output stream. Not sure if anyone could help me with that as I have just tried many things and some of it worked, but unfortunately nothing was pointing me into this direction.
os.write(body.getBytes("UTF-8"));
My issue is with the writeArgsToConn() function.....i think. I cant figure out how to implement it.
I am trying to post multipart-formdata from an Android device using AsyncTask class. Can anyone help with this? I want to stay away from the depreciated org.apache.http.legacy stuff and stick with up-to-date Android libraries.
I was able to use similar implementation for a class called DoPostJSON which used Content-Type: application/json and that class works fine.
Same question but on Reddit: https://redd.it/49qqyq
I had issues with getting nodejs express server to detect the parameters being sent in. My DoPostJSON class worked fine and my nodejs server was able to detect parameters...for some reason DoPostMultiPart doesnt work and nodejs server cant see paramters being passed in. I feel like I am using the library the wrong way.
public class DoPostMultiPart extends AsyncTask<JSONObject, Void, JSONObject> implements Post{
#Override
public HttpURLConnection createConn(String action) throws Exception{
URL url = new URL(Utils.host_api + action);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Cache-Control", "no-cache");
conn.setReadTimeout(35000);
conn.setConnectTimeout(35000);
return conn;
}
#Override
public JSONObject getResponse(HttpURLConnection conn) throws Exception {
int responseCode = conn.getResponseCode();
String response = "";
if (responseCode == HttpsURLConnection.HTTP_OK) {
InputStream in = new BufferedInputStream(conn.getInputStream());
BufferedReader responseStreamReader = new BufferedReader(new InputStreamReader(in));
String line = "";
StringBuilder stringBuilder = new StringBuilder();
while ((line = responseStreamReader.readLine()) != null)
stringBuilder.append(line).append("\n");
responseStreamReader.close();
response = stringBuilder.toString();
} else {
throw new Exception("response code: " + responseCode);
}
conn.disconnect();
return new JSONObject(response);
}
// TODO: fix this function
#Override
public void writeArgsToConn(JSONObject args, HttpURLConnection conn) throws Exception {
// define paramaters
String fullname = args.getString("fullname");
String email = args.getString("email");
String password = args.getString("password");
String confpassword = args.getString("confpassword");
Bitmap pic = (Bitmap) args.get("pic");
// plugin paramters into request
OutputStream os = conn.getOutputStream();
// how do I plugin the String paramters???
pic.compress(Bitmap.CompressFormat.JPEG, 100, os); // is this right???
os.flush();
os.close();
}
#Override
protected JSONObject doInBackground(JSONObject... params) {
JSONObject args = params[0];
try {
String action = args.getString("action");
HttpURLConnection conn = createConn(action);
writeArgsToConn(args, conn);
return getResponse(conn);
} catch (Exception e) {
Utils.logStackTrace(e);
return null;
}
}
}
I solved my issue by using OkHttpClient library.
JSONObject args = params[0];
try
{
final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");
RequestBody requestBody = new MultipartBuilder()
.type(MultipartBuilder.FORM)
.addFormDataPart("fullname", args.getString("fullname"))
.addFormDataPart("email", args.getString("email"))
.addFormDataPart("password", args.getString("password"))
.addFormDataPart("confpassword", args.getString("confpassword"))
.addFormDataPart("pic", "profile.png", RequestBody.create(MEDIA_TYPE_PNG, (File) args.get("pic")))
.build();
Request request = new Request.Builder()
.url(Utils.host_api + args.getString("action"))
.post(requestBody)
.build();
OkHttpClient client = new OkHttpClient();
Response response = client.newCall(request).execute();
return new JSONObject(response.body().string());
}
catch (Exception e)
{
Utils.logStackTrace(e);
return null;
}
When I invoke my Webservice I am getting error like below, please explain it how I can solve this problem.
Error is:
fault Description : nulldetail : faultCode:Server.Processing
faultString:'javax.net.ssl.SSLHandshakeException : General SSLEngine
problem' faultDetail:'null'
I am using tomcat server in my local.
I'm using 1.6 Java Runtime Environment and I added Webservice SSL into:
jdk1.6>jre>lib>security>cacerts .
but nothing changed. Do I need configure my tomcat server
I solved the problem . You dont need to any configuration your server . Or JRE .
Just put it this code
public String retrieveMngTracking(ArrayList paramList) throws Exception {
//ı added for SSL
HostnameVerifier hv = new HostnameVerifier() {
public boolean verify(String urlHostName, SSLSession session) {
System.out.println("Warning: URL Host: " + urlHostName
+ " vs. " + session.getPeerHost());
return true;
}
};
ParamMap paramMap = FlexUtil.getParamMap(paramList);
URL url = new URL(paramMap.getString("url"));
//Call this function for SSL
trustAllHttpsCertificates();
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setReadTimeout(20000);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-type",
"application/x-www-form-urlencoded");
OutputStream os = conn.getOutputStream();
OutputStreamWriter wr = new OutputStreamWriter(os);
wr.write("pMusteriNo=" + paramMap.getString("pMusteriNo"));
wr.write("&pSifre=" + paramMap.getString("pSifre"));
wr.write("&pSiparisNo=" + paramMap.getString("pSiparisNo"));
wr.write("&pKriter=" + paramMap.getString("pKriter"));
wr.flush();
wr.close();
os.close();
StringBuffer sb = new StringBuffer();
BufferedReader br = new BufferedReader(new InputStreamReader(
conn.getInputStream()));
String response = "";
for (;;) {
String line = br.readLine();
if (line == null)
break;
response += line + "\n";
}
br.close();
conn.disconnect();
return response;
}
public static class miTM implements javax.net.ssl.TrustManager,
javax.net.ssl.X509TrustManager {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public boolean isServerTrusted(
java.security.cert.X509Certificate[] certs) {
return true;
}
public boolean isClientTrusted(
java.security.cert.X509Certificate[] certs) {
return true;
}
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType)
throws java.security.cert.CertificateException {
return;
}
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType)
throws java.security.cert.CertificateException {
return;
}
}
private static void trustAllHttpsCertificates() throws Exception {
// Create a trust manager that does not validate certificate chains:
javax.net.ssl.TrustManager[] trustAllCerts =
new javax.net.ssl.TrustManager[1];
javax.net.ssl.TrustManager tm = new miTM();
trustAllCerts[0] = tm;
javax.net.ssl.SSLContext sc =
javax.net.ssl.SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, null);
javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(
sc.getSocketFactory());
}
Ok everything perfect in my local my local server is tomcat . But When ı want to deploy Weblogic server same error giving . Please explain it why everything work my local but now weblogic server problem.
I'm building an application that needs to login to a certain page and make a navigation. I can login, provided that the response contains a string that identifies it. But when I navigate to the second page, I can't see the page as a logged user, only as anonymous.
I'll provide my code:
import java.net.*;
import java.security.*;
import java.security.cert.*;
import javax.net.ssl.*;
import java.io.*;
import java.util.*;
public class PostTest {
static HttpsURLConnection conn = null;
static String sessionId = null;
private static class DefaultTrustManager implements X509TrustManager {
#Override
public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}
#Override
public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}
#Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
public static void main(String[] args) {
try {
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(new KeyManager[0], new TrustManager[] {new DefaultTrustManager()}, new SecureRandom());
SSLContext.setDefault(ctx);
String data = URLEncoder.encode("txtUserName", "UTF-8") + "=" + URLEncoder.encode(/*username*/, "UTF-8");
data += "&" + URLEncoder.encode("txtPassword", "UTF-8") + "=" + URLEncoder.encode(/*password*/", "UTF-8");
data += "&" + URLEncoder.encode("envia", "UTF-8") + "=" + URLEncoder.encode("1", "UTF-8");
connectToSSL(/*login url*/);
//throws java.lang.IllegalStateException: Already connected
conn.setDoOutput(true);
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
wr.write(data);
wr.flush();
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
String resposta = "";
while((line = rd.readLine()) != null) {
resposta += line + "\n";
}
System.out.println("valid login -> " + resposta.contains(/*string that assures me I'm looged in*/));
connectToSSL(/*first navigation page*/);
rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
while((line = rd.readLine()) != null) {
System.out.println(line);
}
} catch(Exception e) {
e.printStackTrace();
}
}
private static void connectToSSL(String address) {
try {
URL url = new URL(address);
conn = (HttpsURLConnection) url.openConnection();
conn.setHostnameVerifier(new HostnameVerifier() {
#Override
public boolean verify(String arg0, SSLSession arg1) {
return true;
}
});
if(sessionId == null) {
sessionId = conn.getHeaderField("Set-Cookie");
}
} catch(Exception ex) {
ex.printStackTrace();
}
}
}
Any further information, just ask.
In connectToSSL, you are opening a new connection each time. In second connection, it will not have any attribute from first connection.
You may want to set get some token/cookie value after fist login connection and use the same in subsequent calls by e.g.
After first connection:
String sessionId = conn.getHeaderField("Set-Cookie");
In subsequent connections:
conn.setRequestProperty("Cookie", sessionId );
Take a look at the Apache Commons project HttpClient. It will help you do what you are trying to accomplish. You need sometime much more complex than a URL class. It needs to maintain a lot of information to go from one authentication request to subsequent authenticated requests.
The site you're accessing probably uses cookies to identify logged in sessions. You'll need to save cookies set on the first request and send them on subsequent requests.
If you're using HttpsUrlConnection, see Cookie Management and java.net.CookieManager. Another choice would be Apache HttpComponents which do cookie management by default.
http is a stateless protocol.
to retain state( sessions) store the cookies received from the server.
List<String> cookies = conn.getHeaderFields().get("Set-Cookie");
send them to server in subsequent requests
for (String cookie : cookies) {
//remove expires and path from cookie
String cookieValue=cookie.substring(0, cookie.indexOf(';');
conn.addRequestProperty("Cookie",cookieValue);
}
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
wr.write(data);