I am interested in a way to programmatically log into OWA (Microsoft Outlook Web Access - a web-based email client) from Java code and retrieve nothing more than the inbox unread count -- I can read this number from the inbox web page's HTML source - but the problem is getting there - logging in.
Essentially, from looking at the HTML source of the OWA logon page, I can see that there is an HTML form element:
<form action="owaauth.dll" method="POST" name="logonForm" autocomplete="off">
that gets submitted by a button element within it:
<input type="submit" class="btn" value="Log On" onclick="clkLgn()">
From investigating the clkLgn() script, I find that it sends a cookie to the document so it may not be crucial:
function clkLgn()
{
if(gbid("rdoPrvt").checked)
{
var oD=new Date();
oD.setTime(oD.getTime()+2*7*24*60*60*1000);
var sA="acc="+(gbid("chkBsc").checked?1:0);
var sL="lgn="+gbid("username").value;
document.cookie="logondata="+sA+"&"+sL+";expires="+oD.toUTCString();
}
}
Basically, how can I send this form?
The following code is my attempt at the problem, I can make the HTTP connection - but I can't seem to be able to POST the correct HTTP request.
URL urlObject = new URL(url);
HttpURLConnection hConnection = (HttpURLConnection)urlObject.openConnection();
HttpURLConnection.setFollowRedirects(true);
hConnection.setDoOutput(true);
hConnection.setRequestMethod("POST");
PrintStream ps = new PrintStream(hConnection.getOutputStream());
ps.print("username="+username+"&password="+password);
ps.close();
hConnection.connect();
if( HttpURLConnection.HTTP_OK == hConnection.getResponseCode() )
{
InputStream is = hConnection.getInputStream();
OutputStream os = new FileOutputStream("output.html");
int data;
while((data=is.read()) != -1)
{
os.write(data);
}
is.close();
os.close();
hConnection.disconnect();
}
It just keeps returning the same logon HTML page.
That JavaScript does certainly an important thing: it adds a cookie to the document. A decent HTTP client is required to send all valid cookies along the headers on every HTTP request. You should do the same programmatically. You can add headers using URLConnection#setRequestProperty().
Further, there are several things to take into account as well when submitting forms programmatically: you should not skip any hidden input fields (input type="hidden"), those might be of relevance. You should also send the name=value pair of the submit button you'd like to press programmatically along as request parameter. Finally, you should not be using & to concatenate parameter pairs, but &.
Note that I don't guarantee that it will finally work, that OWA thing might have some other prevention against bots, but it should solve the as far spotted problems.
See also:
How to use URLConnection?
By the way, have you considered just connecting it using a SMTP/IMAP API like JavaMail?
Why go through a form? MS recently open sourced a Java client for their Exchange server API.
http://blogs.office.com/2014/08/28/open-sourcing-exchange-web-services-ews-java-api/
https://github.com/OfficeDev/ews-java-api
Related
I am trying to send a request using jsoup with manually inserted cookies for the purpose of detecting SQL injection vulnerability.
The problem seams to be that only one of the cookies works and i don't understand why.
I first authenticate myself manually and get the cookies. Example:
PHPSESSID : b74302c3c6af62d23047a450a40cbf5a
security : high
After i got the cookies i send my request (which whould look like this from the browser http://localhost:8090/dvwa/vulnerabilities/sqli/?id='&Submit=Submit#) using the same PHPSESSID but with Security : low. The purpose is to force a "You have an error in your SQL syntax" response that signals SQL Injection vulnerability. The problem is that the PHPSESSID is received good (since I retrieve the dvwa/vulnerabilities/sqli page and not Login page thus it recognizes the PHPSESSID as valid after authentication) but the "security : low" seems not to work. I can't find the problem.
The jsoup code for an initial connection so that i can parse the forms on the page looks like this. I supply the cookies manually.
Connection connection = Jsoup.connect(urlDTO.getUrl())
.userAgent(StringConstants.USER_AGENT)
.cookies(cookies)//Map<String,String>
.referrer(StringConstants.REFERRER);
Document htmlDocument = connection.get();
For sending the form i use this code:
Connection connection = Jsoup.connect(formDTO.getUrl())
.userAgent(StringConstants.USER_AGENT)
.cookies(cookies)
.data(listToMap(formDTO.getInputList()))// id = ' , Submit = Submit
.method(getMethod(formDTO.getMethod()))
.referrer(StringConstants.REFERRER);
Connection.Response res = connection.execute();
Document doc = res.parse();
Does anyone know what I'm doing wrong?
After much debugging I fund out the origin of the problem and the odd behavior. There was no problem with the cookies/headers/url, the problem was at the .method(). The default value of .method() is Method.GET. But since i was sending dynamic requests i had to construct this dynamically also. For this purpose i was parsing the forms to get the method and then adding the type needed in the connection construction.
if (method.equals("post")) {
return Method.POST;
}
if (method.equals("get")) {
return Method.GET;
}
return Method.POST;
This worked until now and surprisingly when sending the wrong method it still sent a response almost valid, so i overlooked it.
Here is the fix.
if (method.toLowerCase().equals("post")) {
return Method.POST;
}
if (method.toLowerCase().equals("get")) {
return Method.GET;
}
return Method.GET;
It was my mistake and not relay a Jsoup problem but since I overlooked it others might too so here is a reminder.
I am trying to simulate an auto login behaviour to a website and scrap the HTML after logging in by using Prowser library in Java.
Code fragment:
<br>
Prowser prowser = new Prowser();<br>
Tab tab = prowser.createTab();<br>
Request request;<br>
String html ="";<br>
try {<br>
request = new Request("http://username:password#www.gmail.com");<br>
Response response = tab.go(request);<br>
html = response.getPageSource();<br>
} catch (Exception e) {<br>
e.printStackTrace();<br>
}<br>
System.out.println(html);<br>
With this code I am able to login and scrap out the HTML if my username doesn't contains #. But if username is an emailId then this doesn't works and returns null.
Any suggestions how to use this library when my username has # in it. Or any other library suitable for what I am trying to do.
Thanks.
I believe that you cal URL-encode it using %40 (which is #). The server should be able to decode it properly, but of course... it depends on the server implementation.
I have to print on a jsp page some images that i get in the form of InputStream.
First i have servlet that passes a variable containing an InputStream to a jsp page, this way:
request.setAttribute("Image", InputStream);
request.getRequestDispatcher(pagename).include(request, response);
In my jsp page i have this to get that InputStream:
${requestScope.VariableContainingInputStream}
To turn that InputStream into an image i should use a servlet this way:
<img src="ServletName">
How can i pass that InputStream to that servlet?
How can i pass that InputStream to that servlet?
You wouldn't. Your JSP would create a temporary (or permanent) file and would write the contents of the InputStream to it. You'd then provide an endpoint that would serve up the content of that file.
You would then provide the URL to that endpoint in your JSP's <img> element.
If you get it as an InputStream, I assume the image is generated dynamically or generally speaking that you have something that gives it to you depending of a number of parameters.
You should think about how a normal (or stupid ...) browser will work :
the user clicks on a link, a submit button or pass an url in adress bar
the browser generate the corresponding request and sends it to the server
the server generate a (generally HTML) page containing links to images and sends it back to browser
the browser analyzes the page, and sends separate requests for the images
the server sends back the image one for each request
the browser display full page containing images
(you could replace images by css pages, js scrips, or any other resources)
So you should not get the input stream at the time of running your jsp to compose the HTML page but write in it <image source=/ImageServlet_url?params_for_current_image/>
Then when the browser will ask for the image, the image servlet will ask for the InputStream and put it directly in response body, with the correct type in the response headers.
This is by far the most robust way of solving your problem. If really it is not an option and the InputStream is only disponible at the moment of running the jsp, you must put in in a session attribute. Then when the ImageServlet will be called, it will look for it in the session and sends it. The problem is that an InputStream in not necessarily Serializable and it is unsafe to put non serializable items in session. So you should :
set a global Hash<String, InputStream> somewhere in your app
when trying to put the InputStream in session, actually put in in the hash (with a unique key) and store the key in session
when getting the InputStream from session, get the key from the session and fetch the InputStream from the hash ... and do not forget to remove it form the hash ...
I strongly advice you to stick to the first solution, not speaking or network errors or power outages between the request of the HTML page and the image ...
I have one application where i have three jsp pages, from index.jsp , control goes to process.jsp and after execution control goes to result.jsp to display data. But i want that instead of displaying data in result.jsp, control will go to another url so that that receiver url will get the requested data. that is: my url is 100.20.3.45:8085/myproject/index.jsp then after processing data i want that result should go to a different url of my same network i.e. 100.20.3.46. How can I send the requested data to this different url?
Ex:
100.20.3.45:8085/myproject/index.jsp
goes to
100.20.3.45.8085/myproject/process.jsp
after processing control will go to 100.20.3.46.
How can I send this data to a different url? what is this mechanism called?
It's called "redirecting". It's to be achieved by HttpServletResponse#sendRedirect().
response.sendRedirect(url);
If you want to send additional data along, you'd need send it as request parameter(s) in a query string, but they will be visible in the URL in browser's address bar. If that isn't affordable, consider storing it in a shared datastore (database?) and then pass alone the unique key along.
Alternatively, you can also just let the <form> action URL point to that different host directly without the need for an intermediate JSP. As another alternative, you could also play for proxy yourself with help of for example URLConnection.
Unrelated to the concrete problem: having controller/business logic in JSPs is a bad practice. I suggest to take some time to learn about servlets.
Redirect to URL
window.location.href = "url"
Examples of use
window.location.href = "/process_payment";
var username = #json($username);
window.location.href = '/' + username;
window.location.href = '/{{ $username }}';
I have a jsp containing a jquery post to a servlet on my tomcat server which creates a HttpServletRequest. I would like to ensure that only my jsp's calls to my servlet are processed and any requests originating from a source other than my jsp are ignored.
Is there a guaranteed way to see what is the referring page calling my server? I have read that using request.getHeader("referer") can be spoofed so I know I can't rely on that.
Generate an unique string as token, store it in the session and embed it as a hidden input value in the POST form of the JSP and finally check in the servlet if the token is valid.
Basically:
On session creation (in HttpSessionListener#sessionCreated(), for example):
Set<String> tokens = new HashSet<String>();
event.getSession().setAttribute("tokens", tokens);
On preprocessing of the JSP request (in HttpServlet#doGet(), for example):
String token = UUID.randomUUID().toString();
Set<String> tokens = (Set<String>) request.getSession().getAttribute("tokens");
tokens.add(token);
request.setAttribute("token", token);
On processing the JSP itself:
<input type="hidden" name="token" value="${token}" />
On postprocessing of the form submit (in HttpServlet#doPost(), for example):
String token = request.getParameter("token");
Set<String> tokens = (Set<String>) request.getSession().getAttribute("tokens");
if (!tokens.remove(token)) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
// ...
I of course assume that your jQuery.post() functions are written in an unobtrusive way as in $.post(form.action, form.serialize(), callback) so that it simulates exactly the normal synchronous request (in other words, your forms works perfectly fine with JS disabled).
You can create a random cookie for your jsp, then append it to your POST form, and accept only requests with correct cookie value.
You could render a secure token to your JSP and include it in your Ajax call to the Servlet where you could verify it. This also doesn't guarantee that the Ajax call is made using a browser and your Javascript but it at least requires someone to get the secure token from the JSP before making the call.
A similar concept is recommended to mitigate CSRF.
Just a bit of semantics. Requests are created usually from the browser which displays your JSP. You can not stop another program from requesting your JSP and using whatever information you give them to request again.
You CAN stop another webpage that is being viewed in a user's browser from executing a request to your site. This is called Cross-site request forgery. You can mitigate this scenario.
So depending on what you are trying to prevent, CSRF solutions might work for you. You can find a premade solution from your web server. For example, here is Tomcat's