Keep Basic Authorization Alive in HttpURLConnection using API (Java) - java

I am retrieving data through an API using HTTP Basic Authentication in the following way:
for (int i = 1; i < 10000; i++) {
try {
URL newurl = new URL ("SOMEURL" + i + ".json");
HttpURLConnection newconnection = (HttpURLConnection) newurl.openConnection();
newconnection.setRequestMethod("GET");
newconnection.setDoInput(true);
newconnection.setRequestProperty ("Authorization", "Basic " + encoding);
try {
InputStream newcontent = (InputStream)newconnection.getInputStream();
BufferedReader bfReader = new BufferedReader (new InputStreamReader (newcontent));
String newline;
if ((newline = bfReader.readLine()) != null) {
out.println(newline);
}
}
catch(Exception e2) {
}
}
catch(Exception e) {
e.printStackTrace();
}
}
Question: Instead of asking for authentication 10,000 times, can I get the authentication once for the first request, keep it alive, and make the remaining 9999 requests without asking for authentication?
Purpose: Faster processing, less load on the server.
Any comments?

HTTP is designed to be stateless, so there is nothing wrong with your approach. However, you can (but not recommened with an API) you sessions (with cookies) or provide a login URL which will issue a temporary auth token which you can pass.

Related

How to implement jdoodle API to compile and run java programs in Android Studio?

I am creating an android app too write and run java code in an android device using Android studio
we tried using the jdoodle API to compile and run the java code in the app. But whenever we tried to compile the code ye are getting error 400.
Please tell me how can I implement this API so that i can execute a java file.
we are using java language to write the program
Getting error code 400 while executing this:
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
try {
String clientId = "af52e5b3d******c2d81bade***6c055"; //Replace with your client ID
String clientSecret = "e868414f******183267d398d578a448c6a1a70bf8be2896ebc******b013bc"; //Replace with your client Secret
String script = editText.getText().toString();
String language = "java";
String versionIndex = "0";
URL url = new URL("https://api.jdoodle.com/v1/execute");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json");
String input = "{\"clientId\": \"" + clientId + "\",\"clientSecret\":\"" + clientSecret + "\",\"script\":\"" + script +
"\",\"language\":\"" + language + "\",\"versionIndex\":\"" + versionIndex + "\"} ";
System.out.println(input);
OutputStream outputStream = connection.getOutputStream();
outputStream.write(input.getBytes());
outputStream.flush();
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
throw new RuntimeException("Please check your inputs : HTTP error code : " + connection.getResponseCode());
}
BufferedReader bufferedReader;
bufferedReader = new BufferedReader(new InputStreamReader(
(connection.getInputStream())));
StringBuilder results = new StringBuilder();
String output1;
System.out.println("Output from JDoodle .... \n");
while ((output1 = bufferedReader.readLine()) != null) {
results.append(output1);
}
connection.disconnect();
output.setText(results);
} catch (IOException e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
thread.start();
here we are pass
Error code 400 is a server side error. I means the server didn't understand your request. If I was to take a guess it would have to do with your input string. It does not appear to be written in the normal way variables are sent in post. That being said, a server can be written to accept the variables any way it wants to. But if it is the reason this is how the string should look.
name=value&name2=value2
You get the idea. Also JDoodle is a pay service. Most pay services will help you, they don't want to lose a client.

Access Azure web app web service through AAD using MSI

I have an Azure webapp (App Service) running with Tomcat. I'd deployed 2 war applications. WAR-1 provides web service call which return a json files using Springboot. WAR-2 is a web application which call this web services in WAR-1. This webapp has system assigned managed identity (or MSI). In addition, this webapp has authentication on with AAD, using Express configuration.
I can access static pages in WAR-2, after authentication through AAD. Now I need to fetch data from WAR-1. I have a servlet which contains code like this:
String subscriptionId = "xxxx";
String testURL = "https://yyy.azurewebsites.net/war1/person/100";
String resourceId = "https://management.azure.com/";
AppServiceMSICredentials credentials = new AppServiceMSICredentials(AzureEnvironment.AZURE);
Azure azure = Azure.configure()
.withLogLevel(LogLevel.BODY_AND_HEADERS)
.authenticate(credentials)
.withSubscription(subscriptionId);
String token = credentials.getToken(resourceId);
HttpURLConnection conn = (HttpURLConnection) new URL(testURL).openConnection();
conn.setDoOutput(true);
conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
conn.setRequestMethod("GET");
conn.setRequestProperty("Authorization", "Bearer " + token);
int responseCode = conn.getResponseCode();
OutputStream os = conn.getOutputStream();
....
I do able to get a token, but the response code is 500 when I make the GET call.
So my question is ... is this the correct way to do this call ? I did found an articlehttps://dotnetdevlife.wordpress.com/2018/10/22/call-azure-ad-protected-website-using-managed-service-identity-msi/ similar to this situation but it uses .Net. I cannot find any Java equivalent of this.
I tested at my side, and here are my steps:
1. Two apps in one Azure web app.
App1: https://jackdemoapp1.azurewebsites.net/app1/
App2: https://jackdemoapp1.azurewebsites.net/app2/
2. Configure Authentication/Authorization on Azure portal.
And you can get the client ID by clicking into the details, note it down and we will use it in app2:
3. Configure managed identity on Azure portal
To simplify the test, the app1 will just return a "Hello" string.
4. Code in app2
#ResponseBody
#RequestMapping("/")
public String index() {
JSONObject json = new JSONObject();
try {
AppServiceMSICredentials credential = new AppServiceMSICredentials(AzureEnvironment.AZURE);
// As we want to get token for accessing the aad-protected app, change the
// resource to the client ID you get in step 2
String token = credential.getToken("ac07d701-6f7d-462e-8b67-5dffa1df955f");
json.put("token", token);
// The URL for app1 API
String app1 = "https://jackdemoapp1.azurewebsites.net/app1/";
HttpURLConnection conn = (HttpURLConnection) new URL(app1).openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Authorization", "Bearer " + token);
conn.setDoOutput(true);
conn.setDoInput(true);
// Open the connection
conn.connect();
int code = conn.getResponseCode();
if (code >= 200 && code <= 300) {
try (InputStream inputStream = conn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) {
StringBuilder stringBuilder = new StringBuilder();
String line = "";
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line);
}
String response = stringBuilder.toString();
json.put("response", response);
}
} else {
json.put("Error", "Response Code" + conn.getResponseCode());
}
conn.disconnect();
} catch (Exception e) {
json.put("Exception", e.getStackTrace());
}
return json.toString();
}
Result

Encode and decode string with special chars in client-server application

I'm developing my client-server application (server is like a servlet and client is an Android app). I have some difficulties sending information between two entities when the message has special chars (ie: 'è' or others)
On client side I use this code to send the message that can contain special chars:
public static String effettuaPOSTServer (String parameters) {
try {
byte [] parametersBytes = parameters.getBytes("UTF-8");
URL url = new URL("http://" + IP_SERVER + ":" + PORT + PATH_SERVLET);
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setConnectTimeout(10000);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content_Type", "application/x-www-form-urlencoded; charset=utf-8");
connection.setRequestProperty ("Content-Length", String.valueOf (parametersBytes.length));
connection.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
wr.write(parametersBytes);
wr.flush();
wr.close();
BufferedReader br = new BufferedReader (new InputStreamReader(connection.getInputStream(), "UTF-8"));
StringBuilder sb = new StringBuilder ();
String s;
while ((s = br.readLine ()) != null) {
sb.append (s);
sb.append ("\n");
}
return sb.toString();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (ProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
on server side I use this code to send the response (also the response can contain special chars like 'è' and others) (I'm in servlet doPost context so I work with HttpServletRequest request and HttpServletResponse response):
PrintWriter pw = response.getWriter();
...
String content = ...; //the string is formatted in JSON format
pw.println (content);
but on both sides I'm unable to receive and manage the correct strings where I have special chars.
I'm trying a lot of solutions on web about encoding/decoding etc. but without successful result.
How can I fix my problem? Thank you!
EDIT:
for example, immagine my request from client as follow (I report the request in GET format to show simply the case):
http://MY_URL:PORT/MY_PATH?parameter1=value1&parameter2=value2&parameter3=èqualcosaacaso
but on server I receive:
parameter1=value1
parameter2=value2
parameter3=Äqualcosaacaso

Java proxy to intercept requests

We would like to create a simple JAVA proxy server that would gather info from the request headers if need be.
We have implemented the proxy server, pointed our browser to the host and port, and we are able to browse sites that use simple HTTP protocol without an issue.
We support the GET and HEAD HTTP methods.
However, sites that use HTTPS cause an issue, as these initiate a CONNECT method, and we can't get the secure connection up, we are not sure what to send in the response. (Or if we would be able to monitor further requests from that point onward.)
Any suggestions? Any 3rd party implementation would do. But we would like to support HTTP and HTTPS in the same process.
private void intercept() throws IOException {
final DataInputStream socketInput = new DataInputStream(this.socket.getInputStream());
final String httpMessage = RequestHeader.readHttpHeader(socketInput);
//Request header is our own convenience file with utility methods that parses the request header.
requestHeader = new RequestHeader(httpMessage);
try {
if ("GET".equals(requestHeader.getType()) || "HEAD".equals(requestHeader.getType())) {
final URL url = new URL(requestHeader.getUrl());
final HttpURLConnection connectionHttp = (HttpURLConnection) url.openConnection();
connectionHttp.setRequestMethod(requestHeader.getType());
// Send response back to client
final DataInputStream dis = new DataInputStream(connectionHttp.getInputStream());
// Add response header
final StringBuilder sb = new StringBuilder();
sb.append(requestHeader.getHttpVersion() + " " + connectionHttp.getResponseCode() + " "
+ connectionHttp.getResponseMessage() + "\r\n");
final Map<String, List<String>> map = connectionHttp.getHeaderFields();
for (final Map.Entry<String, List<String>> entry : map.entrySet()) {
final String key = entry.getKey();
sb.append(key + " : "
+ entry.getValue().toString().replace("[", "").replace("]", "").replace(",", " ") + "\r\n");
}
sb.append("\r\n");
// Add response content
final DataOutputStream socketOutput = new DataOutputStream(this.socket.getOutputStream());
socketOutput.write(sb.toString().getBytes(), 0, sb.toString().getBytes().length);
final byte[] data = new byte[(int) Short.MAX_VALUE];
int index = dis.read(data, 0, (int) Short.MAX_VALUE);
while (index != -1) {
socketOutput.write(data, 0, index);
index = dis.read(data, 0, (int) Short.MAX_VALUE);
}
socketOutput.flush();
// NOTE this works perfectly fine for HTTP sites. We can intercept the communication properly.
} else if ("CONNECT".equals(requestHeader.getType())) {
// TODO establish connection
// First line of header: CONNECT www.facebook.com:443 HTTP/1.1
// We have tried to send back 200 ok response, but no further requests were sent.
} else {
//Nothing else is supported
return;
}
} catch (final MalformedURLException e) {
System.out.print("MalformedURLException " + e.getMessage());
// return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
} catch (final IOException e) {
System.out.print("IOException " + e.getMessage());
// return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
} finally {
System.out.println("Finished.");
}
}
HTTPComponents supports HTTPS. Also, you don't have to write the socket logic yourself, so there's that.
If I recall right, HTTPS works out of the box, no need for any odd configuration or special ssl calls.

How to maintain sessions in java URLConnection?

I am trying to login to a website and get page source of a page site after I login to the web site with java URLConnection. The problem I am facing is I can't maintain session so server gives me this warning and doesn't let me to get connected:
This system requires the use of HTTP cookies to verify authorization information.
Our system has detected that your browser has disabled HTTP cookies, or does not support them.
Please refer to the Help page in your browser for more information on how to correctly configure your browser for use with this system.
At first I am trying to send empty cookie to let server to understand I am handling sessions but it doesn't give me session id either.
This is my source code:
try {
// Construct data
String data = URLEncoder.encode("usr", "UTF-8") + "=" + URLEncoder.encode("usr", "UTF-8");
data += "&" + URLEncoder.encode("password", "UTF-8") + "=" + URLEncoder.encode("pass", "UTF-8");
// Send data
URL url = new URL("https://loginsite.com");
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
conn.setRequestProperty("Cookie", "SESSID=");
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
wr.write(data);
wr.flush();
// Get the response
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = rd.readLine()) != null) {
System.out.println(line);
}
wr.close();
rd.close();
String headerName=null;
for (int i=1; (headerName = conn.getHeaderFieldKey(i))!=null; i++) {
if (headerName.equals("Set-Cookie")) {
String cookie = conn.getHeaderField(i);
System.out.println(cookie.split(";", 2)[0]);
}
}
} catch (Exception e) {
}
You should use an HTTP library which handles session management and other details of the HTTP protocol for you, e.g. supports Cookies and things like Keep-Alive, Proxies etc. out of the box. Try Apache HttpComponents

Categories

Resources