How to make Servlet recognize caller JSP and session - java

I am building a simple WebApplication using servlets. I am a beginner but have tried to learn the most of this technology. There is something I cannot figure out. One of my servlets is the useful BalusC FileServlet
http://balusc.blogspot.mx/2007/07/fileservlet.html
It responds to GET requests with the required file, nice and clean.
I use this FileServlet to serve CSV files for a Dygraph
http://dygraphs.com/
I have two types of users: guests and admins. Guests should be able to SEE the graph BUT NOT be able to DOWNLOAD the CSV file. Admins should be able to do both.
The fileServlet responds to URL-patterns as: file/* (* is the filename), and it is VERY convenient as the Dygraph reads for a file as specified in an URL.
There is a loginServlet built within this webapp, and I want to be able to avoid the fileservlet to GIVE the file if the user just copy-pastes the URL that is given for the Dygraph. The FileServlet is already capable of getting the session and loggeduser from that session, but I don't know how to detect what was the page that called the GET method. I want the fileservlet to serve the file ONLY when called from within the JSP code, and not from the browser's address bar.
Let me explain a bit:
I mean -as a guest user- the following Javascript code should display the graph (the FileServlet serves the file)
<div id="graphdiv2" style="width:640px; height:480px;">
<script type="text/javascript">
g2 = new Dygraph(
document.getElementById("graphdiv2"),
"${messages.rutacsv}", // path to CSV file
{
rollPeriod: 10,
showRoller: true
}
);
</script>
</div>
The variable:
"${messages.rutacsv}" gets replaced by the servlet for something that looks like this:
"file/2012-04-20_1.csv"
So the Dygraph loads the file nicely and plots the lines.
BUT, I want the FileServlet to be able to detect when the user copypastes this URL after the ContextName and block it, so only the Dygraph can download the file.
For example, if the user types in his browser:
http://localhost:8080/MyWebApp/file/2012-04-20_1.csv
It shouldn't be able to download it. Only admins should be able to.
NOW, I am thinking that maybe I should implement the FileServlet so it has to be called with another URL pattern or with a POST method so a simple user copy-pasta can't get past the "origining-JSP" check.
BTW, I'm coming back from trying with Struts2, which is by far too complicated for this application. I abandoned it for convenience and ease of development with simple servlets and JSPs.

Use a filter to check a user role. That's, before the any important action is necessary to check whether the user has a right to this action. This is the task servlet filter.
You must implement the method doFilter() in your class extending javax.servlet.Filter as follows:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpSession session = req.getSession();
String currentRole = (String) session.getAttribute("userRole");
if ("admin".equals(currentRole)) {
successRedirect();
} else {
failRedirect();
}
chain.doFilter(request, response);
}
And don't forget map this filter to the needed address in the web.xml file:
<filter>
<filter-name>CheckRightAccessFilter</filter-name>
<filter-class>yourproject.CheckRightAccessFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CheckRightAccessFilter</filter-name>
<url-pattern>*.csv</url-pattern>
</filter-mapping>

Use servlet filter who check the submiited url and on the basis of the session object it identifies the user role. If it finds the authorized user then it can redirct to the download page

Related

How to pass values from JSP to Servlet without performing event?

I have crated a portlet, Where I am doing my business logic in servlet. But I am getting the liferay login user details in the jsp page. So Now I need to pass the user details while hitting the servlet. This is my JSP code,
<%
String fullname= user.getFullName();
out.println("Full name is: "+fullname+ "...");
long id = themeDisplay.getLayout().getGroupId();
out.println("Site ID is: "+id+ "...");
long userId = themeDisplay.getUserId();
out.println("User ID is: "+userId+ "...");
%>
I need to access the above details in the servlet. How can I do that? Each login user has some different credentials, So all the values should update in and need to access in the servlet. what is the best way to access these values without performing any event. I am hitting the servlet from another web service. I need to access in Get OR Post method,
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
//I need to access those login user information here..
}
This will be really hard to do ("really hard" as in "almost impossible"): When you're in a servlet, all the portal's code of identifying the actual user won't run.
In fact, when you look at the HttpServletRequest for a portlet: This will be directed towards the portal and only later be forwarded to the portlet, with the properly constructed context (e.g. logged in user).
When you look at the servlet, this will be directed to your servlet. Your servlet typically lives in a totally different application context. Thus - by servlet specification - it will be totally separated from the portal environment.
Everything that you find to mitigate this limitation will be somewhat of a hack. Some people use cookies or request parameters. But they all are introducing more or less problems. Especially when you speak of webservices that access your servlet, you can't go with cookies.
In the interest of a well maintainable implementation, my recommendation is to change your architecture. Unfortunately you don't give enough context to recommend what to change your architecture to.

In Filters or Servlet to get initial info about the user when user go to the page

I have question:
Look, When user goes to my web page I want to get info about the user from his cookie or special ID which is in database and render for example hello User1 on my page when user on the page.
Where I have to perform this operations in filter.init() before user will request the servlet or on servlet.init() or would be fine to get this particular info in servlet.doGet()???
Thank you.
With best regards.
Generally, you want to use filters to transform input or output, or to set up pre-conditions for your servlets.
In your particular case, because it's so simple, it probably doesn't really matter which one you choose. However having filters perform authentication and authorization is very common, so you could have your filter check the cookie and / or query the database for the user information, and add it as a request attribute. After that, have the servlet do the work of preparing or writing the message, using the prepared request attribute. As a general rule, you don't want to write output in a filter.
In either case, you won't be using the init method of either the filter or the servlet for this task. The init method is called to initialize the filter or servlet when the application server creates the object, and may or may not be called for every request (in fact, it's probably not called for every request).
in your Filter , use method doFilter
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain)
throws java.io.IOException, ServletException {
//check cookie or anything you want
}

How to manipulate jsp hyperlinks in doGet method inside a Servlet?

I'm new in the Java world. I am trying to develop an ACME Demo using a simple CSV file as a database to validate user names and passwords. I wonder if it is possible to make some hyperlinks on the index.jsp page, which will take you to other jsp pages of the same website if you click them. As far as I know hyperlinks will invoke the doGet method inside the servle, where -in my case- you gonna be redirected to those secure jsp if your credentials are valid of course. So it has worked for just one hyperlink and I would like to make things more dynamic no matter how many links are there??!!
jsp
Content1
<!-- Here I would like to add more links -->
Servlet
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
processRequest(request, response);
//response.sendRedirect("login.jsp");
HttpSession session= request.getSession(true);
if ((session.getAttribute("userSession") != null) && (session.getAttribute("userSession").equals(session.getId())))
{
response.sendRedirect("content1.jsp");
// How can my doGet method manage multiple links here?
}
else
{
response.sendRedirect("login.jsp");
}
}
You should use a servlet filter.
A filter is a component that will be invoked for all the requests to a given url-mapping, and/or for all the requests to a given servlet.
The filter can then check if the user is logged in. If he's loged in, it asks the container to proceed, i.e. invoke the target servlet as if there was no filter. If he's not logged in, the filter can return an error, or redirect to a login page, or do whatever it wants.
See http://www.oracle.com/technetwork/java/filters-137243.html for an introduction and examples of servlet filters.

How to protect pdf file with Tomcat filters?

HI,
I am currently running a tomcat instance with struts 1 and I would like tomcat to detect when pdf files are requested in the URL (For example of a link: http://www.***.com/files/action=download&name=myreport.pdf).
At this point I want a java class to be instantiated, then using a pdf API I want to inject a password to a file. The main point here is that I do not want to have the password store in the original pdf file I am serving instead I want the password to be injected at runtime by Tomcat.
Please let me know if you have any ideas, I did a little of research and I came across tomcat filters but I am unsure if this will resolve this problem.
Please note the passwords are store in a database table.
Thanks
From the filter we invoke a Java class to do the actual "injecting of password".
The entry in the web.xml will redirect your call to a particular filter.
<!--web.xml call all calls to .pdf will invoke the particular filter.-->
<filter>
<filter-name>PDF Filter</filter-name>
<filter-class>PDFFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>PDF Filter</filter-name>
<url-pattern>*.pdf</url-pattern>
</filter-mapping>
//This is the actual filter
public class PDFFilter implements Filter
{
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException
{
PDFPasswordInjector pdfPassInject = new PDFPasswordInjector();
//use HttpServletRequestWrapper to get the pdf location/pdf name
pdfPassInject.injectPassword( "<pdf location>" );
chain.doFilter(request, response);
}
}
//Java class to inject the password
public class PDFPasswordInjector
{
public boolean injectPassword( String sPDFName )
{
// retrieve password from DB
// use API to inject password to PDF
}
}
Create a servlet
Set url-pattern to *.pdf
Whenever your pdf url is called, the servlet is executed.
Do whatever you want from the servlet before returning the PDF to the user in response.
It should be fairly straight forward to write a Filter to intercept all requests that return a PDF. Filter's doFilter() method has access to the request and response so you can modify it however you like.
Filters are not the way to solve this particular problem. Filters allow you to modify requests and cause them to be redirected or redispatched to different servlets. But they don't allow you to rewrite the response body. From what I understand, this is what you are trying to do.
You will have to do the PDF file modification in a Servlet, as described in #Aardvocate's answer.

Java servlet as proxy for Apache web server

I have an apache webserver that is used to serve php and static web files. In order to use active directory authentication i've written some code that can connect to AD through JNDI and authenticate usernames passwords and groups. What I would like is to map all requests to pages in apache through my servlet in order to make sure that a valid session is present and then if they have to login again that they have the correct AD group to visit a particular url. My issue is that when I map my servlet to every url with /* it cannot forward requests to the actual pages that I'm trying to get. It just keeps forwarding the request to my servlet and calling its doGet method till a servlet exception occurs. I want the functionality of a transparent proxy but I cannot seem to get that from this. Does anyone have any concrete examples of a transparent proxy servlet or know a way to do this with servlets. The forwarding functionality of a servlet seems to make this a perfect vehicle for doing it but I seem to be stuck.
Filter code
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest)request;
HttpServletResponse res = (HttpServletResponse)response;
boolean authenticated = false; //should be false when testing is done.
//skip if its the login page
if(req.getRequestURI().equals("/auth/login.jsp") || authenticated){
chain.doFilter(req, res);
}else{
req.setAttribute("protectedUrl", req.getRequestURI());
res.sendRedirect("/auth/login.jsp");
}
}
Web.xml
(snip)
<filter-mapping>
<filter-name>SessionFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
Because the servlet is mapped on /*, the RequestDispatcher#forward() will call it again, resulting in an infinite loop and finally a StackOverflowError (or some other exception depending on the servletcontainer in question which might have some recursion prevention builtin which kicks in after a certain amount of recursive calls).
After all, the Servlet is not entirely the right tool for the job, you'd rather like to use a Filter here. Implement javax.servlet.Filter and do the same job in doFilter() method. It won't call itself recursively when mapped on /* since it by default listens on requests only, not on forwards or includes.

Categories