Servlet request to another servlet with authorization - java

I have tomcat server with some applications. This server uses standart j_secure_check auth. On another tomcat server I need to deploy application that must be some proxy to first server. So I need to invoke servlet from another servlet but first I need to do authentication with j_secure_check. Is it possible to do it programmely?

You need to grab the session cookie and pass it through on subsequent requests.
String url = "http://example.com/j_security_check?j_username=foo&j_password=bar";
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
if (connection.getResponseCode() == 200) { // 200 = OK, 401 = unauthorized
String cookie = connection.getHeaderField("Set-Cookie").split(";", 2)[0];
url = "http://example.com/somepage.jsp";
connection = (HttpURLConnection) new URL(url).openConnection();
connection.setRequestProperty("Cookie", cookie);
InputStream input = connection.getInputStream();
// You can now write it to response.getOutputStream().
}

Related

How to create a cookie and use it in HttpURLConnection?

I have the following python code which creates a cookie and adds it to the session. What would be the equivalent java code for it using HttpURLConnection? I basically want to do a HTTP POST request using the generated cookie.
session = requests.session()
session.auth = (username, password)
try:
token = session.get(SITEMINDER_URL % server, verify=False)
session.cookies.update(dict(SMSESSION=json.loads(token.content)['SMSESSION']))
except Exception as ex:
raise Exception("Failed in authenticating with siteminder", ex)
response = session.post(api_url, headers=headers, verify=False, json=data)
You would use something like this:
HttpURLConnection httpconn = < some source to get a HttpURLConnection >;
String cookieName = "SMSESSION"; // note this is the default but SM can use other prefixes
String cookieValue = < your token content >;
httpurl.setRequestProperty("Cookie", cookieName + "=" + cookieValue);
Also, from the javadocs: NOTE: HTTP requires all request properties which can legally have multiple instances with the same key to use a comma-separated list syntax which enables multiple properties to be appended into a single property
Which leads me to pointing out that using the HttpUrlConnection directly is really clumsy. I recommend you look at an HTTP client library such as Apache HTTP Client http://hc.apache.org/httpcomponents-client-ga/
In my opinion, you can just create an HttpUrlConnection object assigning a List of Cookies as follows:
List<String> cookies = new ArrayList<>();
//Or using a map With entries: Key and value for each cookie
cookies.add("User-Agent=MyUserAgent"); //etc...
URL site = new URL("https://myurl.com");
HttpsURLConnection conn = (HttpsURLConnection) site.openConnection();
for (String string: cookies) {
conn.setRequestProperty("Cookie", string);
}
However this is the simplest but not the best way to do so.
To get higher abstraction for Cookie use CookieManager and CookieStore classes. Here is an example:
HttpURLConnection connection
CookieManager cookieManager = new CookieManager();
HttpCookie cookie = new HttpCookie("cookieName","cookieValue");
cookieManager.getCookieStore().add(null,cookie);
connection.setRequestProperty("Cookie", String.join( ";", cookieManager.getCookieStore().getCookies()));
Try This:
URL url = new URL("http://www.example.com");
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setRequestProperty("Cookie", "name1=value1; name2=value2");
conn.connect();

Java doesn't send HTTP POST Request

I'm implementing some simple java class in order to send an HTTP Request with POST method and also another java class in order to receive it.
The server works fine when I make a POST request by means of my browser(Chrome), or an application(I have used Postman in this case) but it ends up with problem when I send HTTP Request with java!
My sending HTTP class is "Sender.java", containing the following snippet:
String url = "http://localhost:8082/";
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
// Setting basic post request
con.setRequestMethod("POST");
//con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
//con.setRequestProperty("Content-Type","text/plain");
// Send post request
con.setDoOutput(true);
OutputStream os = con.getOutputStream();
os.write("Just Some Text".getBytes("UTF-8"));
os.flush();
os.close();
//connect to the Server(resides at Server.java)
con.connect();
I have commented some lines of code setting Headers like "Accept-Language" and "Content-Type" because I don't know whether or not are these headers required for the java program to work out?
The server is another java program named "Server.java". Here is the snippet related to reading HTTP Request made by the Sender.java(if need be).
int servPort = 8082;
// Create a server socket to accept HTTP client connection requests
HttpServer server = HttpServer.create(new InetSocketAddress(servPort), 0);
System.out.println("server started at " + servPort);
server.createContext("/", new PostHandler());//PostHandler implements HttpHandler
server.setExecutor(null);
server.start();
All I want is to send a plaintext as the body of my HTTP Request with the Post method. I have read plenty of sites and even related questions at this site. But it still doesn't work out. In other words, whenever I create an HTTP Request from "Sender.java", nothing appears at "Server.java". I just want to know what's wrong with my snippets and how should I fix that?
I tested this and it's working:
//Sender.java
String url = "http://localhost:8082/";
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
con.setDoOutput(true);
OutputStream os = con.getOutputStream();
os.write("Just Some Text".getBytes("UTF-8"));
os.flush();
int httpResult = con.getResponseCode();
con.disconnect();
As you can see, connect is not necessary. The key line is
int httpResult = con.getResponseCode();
When you send a POST form using the browser, it sends the form in a certain format, defined in RFC1866, you have to recreate this on Java when making a post request.
With this format, its important you set the Content-Type header to application/x-www-form-urlencoded, and pass the body as you would do in a url with a get request.
Borrowing some code of my previous answer to POST in Java:
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
// Setting basic post request
con.setRequestMethod("POST");
Map<String,String> form = new HashMap<>();
// Define the fields
form.put("username", "root");
form.put("password", "sjh76HSn!"); // This is a fake password obviously
// Build the body
StringJoiner sj = new StringJoiner("&");
for(Map.Entry<String,String> entry : arguments.entrySet())
sj.add(URLEncoder.encode(entry.getKey(), "UTF-8") + "="
+ URLEncoder.encode(entry.getValue(), "UTF-8"));
byte[] out = sj.toString().getBytes(StandardCharsets.UTF_8);
int length = out.length;
// Prepare our `con` object
con.setFixedLengthStreamingMode(length);
con.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
con.connect();
try (OutputStream os = con.getOutputStream()) {
os.write(out);
}
Maybe “localhost” in the sender url does not resolve to the same ip that the server binds to? Try changing to 127.0.0.1 or your actual IP address.
try with PrintStream
String url = "http://localhost:8082/";
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
// Setting basic post request
con.setRequestMethod("POST");
//con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
//con.setRequestProperty("Content-Type","text/plain");
// Send post request
con.setDoOutput(true);
OutputStream os = con.getOutputStream();
java.io.PrintStream printStream = new java.io.PrintStream(os);
printStream.println("Just Some Text");
con.getInputStream();//Send request
os.flush();
os.close();

HTTP to HTTPS Redirection in java using HTTPURLConnection

I am facing an Issue while connecting to an HTTP request for a particular url in my java Code. For eg: http://www.linkedin.com . This throws Server Not available Error. (TimeOutException) .
But, I want my connection to redirect http request to Location header Value if responseCode is 301 or 302.
Code Snippet:
HttpURLConnection urlConn =(HttpURLConnection) new URL(url).openConnection(); //For eg : http://www.linkedin.com
urlConn.setConnectTimeout(10*1000);
urlConn.setReadTimeout(10*1000);
boolean redirect = false;
int status = urlConn.getResponseCode(); //No response. Throws exception
if (status == HttpURLConnection.HTTP_MOVED_TEMP || status == HttpURLConnection.HTTP_MOVED_PERM)
{
redirect = true;
}
String contenttype = urlConn.getContentType();
if(redirect)
{
String newUrl = urlConn.getHeaderField("Location");//No I18N
urlConn = (HttpURLConnection) new URL(newUrl).openConnection();
urlConn.connect();
contenttype = urlConn.getContentType();
}
Your code works for me. Obviously, you are facing some network issues.
Is http://www.linkedin.com working in your browser?
If yes , then you can check whether it's using some proxy.

RestEasy client to secured service

We have deployed RestEasy services, as part of application, and secured them with filter (a class that implements javax.servlet.Filter). Filter checks if object of the User class exists in the session. The user object is inserted into session when user logs in. Everything works fine.
However, we need to create standalone app that accesses these services. We decided to use RestEasy client API. We can access these services if the filter is turned off, but how do we perform this logging in and session manipulation from RestEasy client API.
Let's assume your standalone client was written in Java.
Then a sample code would look like this.
First we need to authenticate the user by calling your auth service and obtain a valid session ID. Let's assume the obtained session id is equivalent to "f47cdba8-d066-48e8-ad29-8c4222906bc7". Then we can call the REST service with the valid session ID as a HTTP header parameter.
String url = "http://localhost:8081/AuthService/";
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
// optional default is GET
con.setRequestMethod("GET");
//add request header
con.setRequestProperty("User-Agent", USER_AGENT);
con.setRequestProperty("Authorization", "token=f47cdba8-d066-48e8-ad29-8c4222906bc7");
int responseCode = con.getResponseCode();
System.out.println("\nSending 'GET' request to URL : " + url);
System.out.println("Response Code : " + responseCode);
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
//print result
System.out.println(response.toString());
At the back end you need to process this HTTP header parameter based Session ID and validate the oncoming request before serving it.
Hope this helps.

HttpURLConnection sends a POST request even though httpCon.setRequestMethod("GET"); is set

Here is my code:
String addr = "http://172.26.41.18:8080/domain/list";
URL url = new URL(addr);
HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
httpCon.setDoOutput(true);
httpCon.setDoInput(true);
httpCon.setUseCaches(false);
httpCon.setAllowUserInteraction(false);
httpCon.setRequestMethod("GET");
httpCon.addRequestProperty("Authorization", "Basic YWRtaW4fYFgjkl5463");
httpCon.connect();
OutputStreamWriter out = new OutputStreamWriter(httpCon.getOutputStream());
System.out.println(httpCon.getResponseCode());
System.out.println(httpCon.getResponseMessage());
out.close();
What I see in response:
500 Server error
I open my httpCon var, and what I see:
POST /rest/platform/domain/list HTTP/1.1
Why is it set to POST even though I have used httpCon.setRequestMethod("GET"); to set it to GET?
The httpCon.setDoOutput(true); implicitly set the request method to POST because that's the default method whenever you want to send a request body.
If you want to use GET, remove that line and remove the OutputStreamWriter out = new OutputStreamWriter(httpCon.getOutputStream()); line. You don't need to send a request body for GET requests.
The following should do for a simple GET request:
String addr = "http://172.26.41.18:8080/domain/list";
URL url = new URL(addr);
HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
httpCon.setUseCaches(false);
httpCon.setAllowUserInteraction(false);
httpCon.addRequestProperty("Authorization", "Basic YWRtaW4fYFgjkl5463");
System.out.println(httpCon.getResponseCode());
System.out.println(httpCon.getResponseMessage());
See also:
Using java.net.URLConnection to fire and handle HTTP requests
Unrelated to the concrete problem, the password part of your Authorization header value doesn't seem to be properly Base64-encoded. Perhaps it's scrambled because it was examplary, but even if it wasn't I'd fix your Base64 encoding approach.

Categories