servicenow xml java basic auth is failing - java

Am trying to download xml file for the list of incidents from service now and using below code:
public static void main(String[] args) {
try {
String webPage = "https:/ServicnowURL//incident_list.do?XML&sysparm_query=u_im_record_type...";
String name = "uname";
String password = "Pwd";
String authString = name + ":" + password;
System.out.println("auth string: " + authString);
byte[] authEncBytes = Base64.encodeBase64(authString.getBytes("UTF-8"));
String authStringEnc = new String(authEncBytes);
System.out.println("Base64 encoded auth string: " + authStringEnc);
URL url = new URL(webPage);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestProperty("Authorization", "Basic %s" + authStringEnc);
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty( "Content-type", "text/xml");
urlConnection.setRequestProperty( "Accept", "*/*" );
urlConnection.setRequestProperty( "Accept-Encoding", "gzip" );
System.out.println(urlConnection.getResponseCode());
InputStream is;
if(urlConnection.getResponseCode()==HttpURLConnection.HTTP_OK){
is = urlConnection.getInputStream();
System.out.println(is);
}
else{
is=urlConnection.getErrorStream();
System.out.println(is);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
Am getting 401 unauthorized error for the above code
If I give url as "https:/ServicnowURL//incident_list.do?sysparm_query=u_im_record_type..." by removing "XML" in the url, then I am getting response successfully.

Related

Upload an attachment to azure devops [REST API]

I'm having a hard time adding a attachments in my azure devops repo via api...
public static void putAttachments(Integer id) {
try {
URL url = new URL(
"https://dev.azure.com/marcoparra0034/AgileFr/_apis/wit/attachments?api-version=5.1&fileName=imageAs.png");
HttpURLConnection con = ResApiMain.apiConnectionAttachments(PAT, url);
File file = new File("C:\\Users\\marco.parra\\Pictures\\Screenshots\\new.png");
String base64Image = encodeFileToBase64Binary(file);
// String jsonInputString = "[{\"op\":\"add\",\"path\":\"/fields/System.Title\",\"value\":\"" + "tpain"
// + "\"}]";
base64Image = "[" + base64Image + "]";
System.out.println("Base xs" + base64Image);
try (OutputStream os = con.getOutputStream()) {
byte[] input = Base64.decodeBase64(base64Image.getBytes("utf-8"));
System.out.println(new String(input));
os.write(input, 0, input.length);
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
try (BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), "utf-8"))) {
StringBuilder response = new StringBuilder();
String responseLine = null;
while ((responseLine = br.readLine()) != null) {
response.append(responseLine.trim());
}
System.out.println(response.toString());
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
con.disconnect();
} catch (Exception ex) {
}
This is the connection method
public static HttpURLConnection apiConnectionAttachments(String PAT, URL url) {
HttpURLConnection con = null;
try {
String AuthStr = ":" + PAT;
Base64 base64 = new Base64();
String encodedPAT = new String(base64.encode(AuthStr.getBytes()));
con = (HttpURLConnection) url.openConnection();
con.setRequestProperty("Authorization", "Basic " + encodedPAT);
con.setDoOutput(true);
System.out.println("URL - " + url.toString());
System.out.println("PAT - " + encodedPAT);
// Image Requierements
// con.setRequestProperty("Content-Type", "image/jpeg");
con.setDoInput(true);
con.setUseCaches(false);
con.setRequestProperty("X-HTTP-Method-Override", "PATCH");
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/octet-stream");
// con.setRequestProperty("Accept", "application/json");
} catch (Exception e) {
System.out.println(e.getMessage());
}
return con;
}
When i run this it show the next error code
Server returned HTTP response code: 405 for URL: https://dev.azure.com/marcoparra0034/AgileFr/_apis/wit/attachments?api-version=5.1&fileName=imageAs.png
Update i see how to work with python and c# but i can´t follow this logic to create an attachment
https://github.com/Microsoft/azure-devops-python-api/blob/1bacd2a3f0128a6d184cf75e2c6f8859d46f270a/vsts/vsts/work_item_tracking/v4_1/work_item_tracking_client.py#L56
Expectations Example
{
"id": "a5cedde4-2dd5-4fcf-befe-fd0977dd3433",
"url": "https://dev.azure.com/fabrikam/_apis/wit/attachments/a5cedde4-2dd5-4fcf-befe-fd0977dd3433?fileName=imageAsFileAttachment.png"
}
https://learn.microsoft.com/en-us/rest/api/azure/devops/wit/attachments/create?view=azure-devops-rest-5.1
Any help would be appreciated....
I solve this issue commenting line con.setRequestProperty("X-HTTP-Method-Override", "PATCH");

Android 500 error on image uploading

I am getting 500 server error using multipart. Same server code is working while uploading image from iOS side. Following is my code for multipart image uploading.Server Side is using PHP.
public PostFile(String requestURL)
throws IOException {
// creates a unique boundary based on time stamp
URL url = new URL(requestURL);
httpConn = (HttpURLConnection) url.openConnection();
httpConn.setUseCaches(false);
httpConn.setDoOutput(true); // indicates POST method
httpConn.setDoInput(true);
httpConn.setRequestMethod("POST");
httpConn.setRequestProperty("Connection", "Keep-Alive");
httpConn.setRequestProperty("Cache-Control", "no-cache");
httpConn.setRequestProperty(
"Content-Type", "multipart/form-data;boundary=" + this.boundary);
request = new DataOutputStream(httpConn.getOutputStream());
}
private void saveFile() {
try {
PostFile postFile = new PostFile(URL);
//postFile.addFormField();
postFile.addFormField("userId", "25");
postFile.addFormField("accessToken", "h7lCesyM3XKjmjvjrdojzypUNPqA9MsB8PQIzZyWkYHtV43XcxPubUJ3EV8L");
// contact.accumulate("files",imgData);
postFile.addFormField("area", "dfs");
postFile.addFilePart("test.jpeg", getFileFromBitmap(uri));
postFile.finish();
} catch (IOException e) {
e.printStackTrace();
}
}
public void addFilePart(String fieldName, File uploadFile)
throws IOException {
String fileName = uploadFile.getName();
request.writeBytes(this.twoHyphens + this.boundary + this.crlf);
request.writeBytes("Content-Disposition: form-data; name=\"" +
fieldName + "\";filename=\"" +
fileName + "\"" + this.crlf);
request.writeBytes("Content-Type: image/jpeg;" + this.crlf);
request.writeBytes(this.crlf);
// byte[] bytes = Files.readAllBytes(uploadFile.toPath());
request.write(getBytesFromFile(uploadFile));
}

Https connection Android with Http authentication

I want to make a HTTPS connection with a webservice in Android Studio but it doesn't work with the code that I have written. I get a FileNotFound Exception.
My URL is working in the browser.
And response code is 400.
This is my code:
protected Void doInBackground(String... params) {
String https_url = "HERE MY HTTPS URL";
URL url;
try {
url = new URL(https_url);
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
String userPassword = "USERNAME" + ":" + "PASSWORD";
String encoding = new String(Base64.encode(userPassword.getBytes(), Base64.DEFAULT));
con.setRequestProperty("Authorization", "Basic " + encoding);
con.setRequestProperty("User-Agent","Mozilla/5.0 ( compatible ) ");
con.setRequestProperty("Accept","*/*");
//dumpl all cert info
print_https_cert(con);
//dump all the content
print_content(con);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
Someone who can help me out?

How to setEntity on a HttpURLConnection

In my project I must strictly use HttpURLConnection class
I have this following code which I got from the internet
MultipartEntity multiPart = new MultiPartEntity(HttpMultipartMode.BROWSER_COMPATIBLE, null Chartset.forName("UTF-8");
File f = new File("/home/abhishek/foo.docx");
FileBody fb = new FileBody(f);
multiPart.addPart("file", fb);
HttpPost post = new HttpPost();
post.setHeader("ENCTYPE", "multipart/form-data");
post.setEntity(multiPart);
Problem is that I cannot use HttpPost ... In my project only HttpURLConnection class works!
So I need to translate the code above into HttpURLConnection.
I cannot find anything similar to setEntity on the HttpUrlConnection.
Edit::
Based on the suggestions below. I have this code
public class RESTFileUpload {
public static void main(String[] args) throws Exception {
Authenticator.setDefault(new Authenticator() {
#Override
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("domain\\user", "Password".toCharArray());
}
});
String filePath = "/home/abhishek/Documents/HelloWorld.docx";
String fileName = "HelloWorld.docx";
String fileNameShort = "HelloWorld";
String urlStr = "https://sp.company.com/sites/abhi_test/_vti_bin/listdata.svc/SharedDocuments/RootFolder/Files/add(url=#TargetFileName,overwrite='true')&#TargetFileName=" + fileName;
String crlf = "\r\n";
String twoHypens = "--";
String boundary = "*****";
URL url = new URL(urlStr);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setDoOutput(true);
con.setDoInput(true);
con.setUseCaches(false);
con.setRequestMethod("POST");
con.setRequestProperty("Connection", "Keep-Alive");
con.setRequestProperty("Cache-Control", "no-cache");
con.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
DataOutputStream request = new DataOutputStream(con.getOutputStream());
request.writeBytes(twoHypens + boundary + crlf);
request.writeBytes("Content-Disposition: form-data;name=\"" + fileNameShort + "\";fileName=\"" + fileName + "\"" + crlf);
request.writeBytes(crlf);
request.write(convertToByteArray(filePath));
request.writeBytes(crlf);
request.writeBytes(twoHypens + boundary + twoHypens + crlf);
request.flush();
request.close();
InputStream responseStream = new BufferedInputStream(con.getInputStream());
BufferedReader responseStreamReader = new BufferedReader(new InputStreamReader(responseStream));
String line = "";
StringBuilder strBuilder = new StringBuilder();
while((line = responseStreamReader.readLine()) != null) {
strBuilder.append(line).append("\n");
}
responseStreamReader.close();
String response = strBuilder.toString();
responseStream.close();
con.disconnect();
System.out.println(response);
}
private static byte[] convertToByteArray(String filePath) {
File f = new File(filePath);
byte[] retVal = new byte[(int)f.length()];
try {
FileInputStream fis = new FileInputStream(f);
fis.read(retVal);
}
catch (FileNotFoundException ex) {
ex.printStackTrace();
}
catch(IOException ex2) {
ex2.printStackTrace();
}
return retVal;
}
}
But I get the error
Exception in thread "main" java.io.IOException: Server returned HTTP response code: 400 for URL: https://sp.web.gs.com/sites/abhi_test/_vti_bin/listdata.svc/SharedDocuments/
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1626)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
at RESTFileUpload.main(RESTFileUpload.java:62)
HttpURLConnection has .getInputStream() and .getOutputStream() methods. If you wish to send body content with an Http request, you call .setDoOutput(true) on your HttpURLConnection object, call .getOutputStream() to get an Output stream and then write the content of your entity to the output stream (either as raw bytes, or using a Writer implementation of some sort), closing it when you are finished writing.
For more details, see the API docs for HttpURLConnection here.
To post files using the HttpURLConnection you have to compose the file wrapper manually. Take a look at this answer, it should be helpful for you.

Connecting to remote URL which requires authentication using Java

How do I connect to a remote URL in Java which requires authentication. I'm trying to find a way to modify the following code to be able to programatically provide a username/password so it doesn't throw a 401.
URL url = new URL(String.format("http://%s/manager/list", _host + ":8080"));
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
There's a native and less intrusive alternative, which works only for your call.
URL url = new URL(“location address”);
URLConnection uc = url.openConnection();
String userpass = username + ":" + password;
String basicAuth = "Basic " + new String(Base64.getEncoder().encode(userpass.getBytes()));
uc.setRequestProperty ("Authorization", basicAuth);
InputStream in = uc.getInputStream();
You can set the default authenticator for http requests like this:
Authenticator.setDefault (new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication ("username", "password".toCharArray());
}
});
Also, if you require more flexibility, you can check out the Apache HttpClient, which will give you more authentication options (as well as session support, etc.)
You can also use the following, which does not require using external packages:
URL url = new URL(“location address”);
URLConnection uc = url.openConnection();
String userpass = username + ":" + password;
String basicAuth = "Basic " + javax.xml.bind.DatatypeConverter.printBase64Binary(userpass.getBytes());
uc.setRequestProperty ("Authorization", basicAuth);
InputStream in = uc.getInputStream();
If you are using the normal login whilst entering the username and password between the protocol and the domain this is simpler. It also works with and without login.
Sample URL: http://user:pass#example.com/url
URL url = new URL("http://user:pass#example.com/url");
URLConnection urlConnection = url.openConnection();
if (url.getUserInfo() != null) {
String basicAuth = "Basic " + new String(new Base64().encode(url.getUserInfo().getBytes()));
urlConnection.setRequestProperty("Authorization", basicAuth);
}
InputStream inputStream = urlConnection.getInputStream();
Please note in the comment, from valerybodak, below how it is done in an Android development environment.
As I have came here looking for an Android-Java-Answer I am going to do a short summary:
Use java.net.Authenticator as shown by James van Huis
Use Apache Commons HTTP Client, as in this Answer
Use basic java.net.URLConnection and set the Authentication-Header manually like shown here
If you want to use java.net.URLConnection with Basic Authentication in Android try this code:
URL url = new URL("http://www.example.com/resource");
URLConnection urlConnection = url.openConnection();
String header = "Basic " + new String(android.util.Base64.encode("user:pass".getBytes(), android.util.Base64.NO_WRAP));
urlConnection.addRequestProperty("Authorization", header);
// go on setting more request headers, reading the response, etc
Was able to set the auth using the HttpsURLConnection
URL myUrl = new URL(httpsURL);
HttpsURLConnection conn = (HttpsURLConnection)myUrl.openConnection();
String userpass = username + ":" + password;
String basicAuth = "Basic " + new String(Base64.getEncoder().encode(userpass.getBytes()));
//httpsurlconnection
conn.setRequestProperty("Authorization", basicAuth);
few of the changes fetched from this post. and Base64 is from java.util package.
Be really careful with the "Base64().encode()"approach, my team and I got 400 Apache bad request issues because it adds a \r\n at the end of the string generated.
We found it sniffing packets thanks to Wireshark.
Here is our solution :
import org.apache.commons.codec.binary.Base64;
HttpGet getRequest = new HttpGet(endpoint);
getRequest.addHeader("Authorization", "Basic " + getBasicAuthenticationEncoding());
private String getBasicAuthenticationEncoding() {
String userPassword = username + ":" + password;
return new String(Base64.encodeBase64(userPassword.getBytes()));
}
Hope it helps!
Use this code for basic authentication.
URL url = new URL(path);
String userPass = "username:password";
String basicAuth = "Basic " + Base64.encodeToString(userPass.getBytes(), Base64.DEFAULT);//or
//String basicAuth = "Basic " + new String(Base64.encode(userPass.getBytes(), Base64.No_WRAP));
HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
urlConnection.setRequestProperty("Authorization", basicAuth);
urlConnection.connect();
Since Java 9, you can do this
URL url = new URL("http://www.example.com");
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setAuthenticator(new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication ("USER", "PASS".toCharArray());
}
});
I'd like to provide an answer for the case that you do not have control over the code that opens the connection. Like I did when using the URLClassLoader to load a jar file from a password protected server.
The Authenticator solution would work but has the drawback that it first tries to reach the server without a password and only after the server asks for a password provides one. That's an unnecessary roundtrip if you already know the server would need a password.
public class MyStreamHandlerFactory implements URLStreamHandlerFactory {
private final ServerInfo serverInfo;
public MyStreamHandlerFactory(ServerInfo serverInfo) {
this.serverInfo = serverInfo;
}
#Override
public URLStreamHandler createURLStreamHandler(String protocol) {
switch (protocol) {
case "my":
return new MyStreamHandler(serverInfo);
default:
return null;
}
}
}
public class MyStreamHandler extends URLStreamHandler {
private final String encodedCredentials;
public MyStreamHandler(ServerInfo serverInfo) {
String strCredentials = serverInfo.getUsername() + ":" + serverInfo.getPassword();
this.encodedCredentials = Base64.getEncoder().encodeToString(strCredentials.getBytes());
}
#Override
protected URLConnection openConnection(URL url) throws IOException {
String authority = url.getAuthority();
String protocol = "http";
URL directUrl = new URL(protocol, url.getHost(), url.getPort(), url.getFile());
HttpURLConnection connection = (HttpURLConnection) directUrl.openConnection();
connection.setRequestProperty("Authorization", "Basic " + encodedCredentials);
return connection;
}
}
This registers a new protocol my that is replaced by http when credentials are added. So when creating the new URLClassLoader just replace http with my and everything is fine. I know URLClassLoader provides a constructor that takes an URLStreamHandlerFactory but this factory is not used if the URL points to a jar file.
i did that this way you need to do this just copy paste it be happy
HttpURLConnection urlConnection;
String url;
// String data = json;
String result = null;
try {
String username ="user#gmail.com";
String password = "12345678";
String auth =new String(username + ":" + password);
byte[] data1 = auth.getBytes(UTF_8);
String base64 = Base64.encodeToString(data1, Base64.NO_WRAP);
//Connect
urlConnection = (HttpURLConnection) ((new URL(urlBasePath).openConnection()));
urlConnection.setDoOutput(true);
urlConnection.setRequestProperty("Content-Type", "application/json");
urlConnection.setRequestProperty("Authorization", "Basic "+base64);
urlConnection.setRequestProperty("Accept", "application/json");
urlConnection.setRequestMethod("POST");
urlConnection.setConnectTimeout(10000);
urlConnection.connect();
JSONObject obj = new JSONObject();
obj.put("MobileNumber", "+97333746934");
obj.put("EmailAddress", "danish.hussain#example.com");
obj.put("FirstName", "Danish");
obj.put("LastName", "Hussain");
obj.put("Country", "BH");
obj.put("Language", "EN");
String data = obj.toString();
//Write
OutputStream outputStream = urlConnection.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream, "UTF-8"));
writer.write(data);
writer.close();
outputStream.close();
int responseCode=urlConnection.getResponseCode();
if (responseCode == HttpsURLConnection.HTTP_OK) {
//Read
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), "UTF-8"));
String line = null;
StringBuilder sb = new StringBuilder();
while ((line = bufferedReader.readLine()) != null) {
sb.append(line);
}
bufferedReader.close();
result = sb.toString();
}else {
// return new String("false : "+responseCode);
new String("false : "+responseCode);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
ANDROD IMPLEMENTATION
A complete method to request data/string response from web service requesting authorization with username and password
public static String getData(String uri, String userName, String userPassword) {
BufferedReader reader = null;
byte[] loginBytes = (userName + ":" + userPassword).getBytes();
StringBuilder loginBuilder = new StringBuilder()
.append("Basic ")
.append(Base64.encodeToString(loginBytes, Base64.DEFAULT));
try {
URL url = new URL(uri);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.addRequestProperty("Authorization", loginBuilder.toString());
StringBuilder sb = new StringBuilder();
reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
while ((line = reader.readLine())!= null){
sb.append(line);
sb.append("\n");
}
return sb.toString();
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
if (null != reader){
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

Categories

Resources