Allowing download servlet only for users who are logged in - java

I implemented a download servlet based on #wen's answer in Implementing a simple file download servlet
web.xml
<servlet>
<servlet-name>DownloadServlet</servlet-name>
<servlet-class>com.myapp.servlet.DownloadServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DownloadServlet</servlet-name>
<url-pattern>/download</url-pattern>
</servlet-mapping>
DownloadServlet.java
public class DownloadServlet extends HttpServlet {
protected void doGet( HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String id = request.getParameter("id");
String fileName = "";
String fileType = "";
How can I prevent the download servlet being activated by someone who is not logged in.
I have a ClientSession object that holds all the details of the login but I do not know how to access it from within the download servlet.
For instance, if I put a token in the request, then how could I validate this token against the ClientSession object.

You should get the client session from the HttpSession.
ClientSession clientSession = (ClientSession) request.getSession().getAttribute("client_session_info");
Naturally when you log in you must store your clientSession into the HttpSession like this:
session.setAttribute("client_session_info", clientSession);
I don't know how you log your user, but you should be able to access the http session object and store your data into it.

Related

Java login authentication

Hey there just got some questions i want to validate before i will start implementing login flow on my website.
So basically which way is safer / better / more optimal to do.
Let's get to the point. What I'am trying to achieve is some kind of control panel for administrator, its seperate website which allows to manage very important data.
How i want it work is to make it as secure as possible meanwhile being optimized because data will be displayed live through sockets.
So let's get to the point..
url.com/ is root url, which consists of login panel, I want to hide other page's so no one can access them meanwhile authoriziting users.
Before i start with authorization method i got a question about authentication (not sure if named them right =P)
Which authentication is safer, i send POST with username / password and should i return token which i shall save in sessionStorage and then send token with every request (that's how i did it with my REST API) or should i do it in java with.
//validate with db and if valid.
HttpSession session = request.getSession();
session.setAtrribute("token",token);
So i red a bit and came to this conclusion.
Method no.1 creating a filter for all pages which prevents from accessing them through URL.
#WebFilter("/*")
public class LoginFilter implements Filter {
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
HttpSession session = request.getSession(false);
if (session == null || session.getAttribute("token") == null) {
response.sendRedirect(request.getContextPath() + "/");
} else {
//check if token is not expires or if exists with database
chain.doFilter(req, res); // Logged-in user found, so just continue request.
}
}
}
Method no.2 using servlets to map urls and read them from WEB-INF.
#WebServlet("/dashboard")
public class SearchServlet extends HttpServlet {
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException{
request.getRequestDispatcher("/WEB-INF/dashboard.html").forward(request, response);
}
}
and reading from WEB-INF would be in doPOST method, with token sent in header Authoriization, if valid then redirect to page from WEB-INF else to login.
If my question is somehow dumb im sorry, i'am 2nd year student and still learning.

Losing Session on POST

I have been trying to find the reason as to why my session would be lost when I do a POST.
I am checking my session all throughout my app but the session will drop when I call a particular servlet and it only drops on this particular one. The issue is intermittent so it is very frustrating. I'm not sure what is needed so I'll put as much info as I can up.
The page is accessed through a servlet. I can verify that the session is still the same.
As the user is routing through the app, I can see that the session is still the same.
Checking Session:HTTP Session CEHKIIMEKHMH
Calling Get Details
Checking Session:HTTP Session CEHKIIMEKHMH
Calling Project Details
Checking Session:HTTP Session CEHKIIMEKHMH
Calling Attachment Controller
Checking Session:HTTP Session CEHKIIMEKHMH
public class Attachments extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("Calling Attachment Controller");
HttpSession session = request.getSession(false);
System.out.println("Checking Session:"+session);
if(session != null){
Object projectId = session.getAttribute("projectId");
request.getRequestDispatcher(response.encodeURL("views/attachments.jsp")).forward(request, response);
}else{
System.err.println("Invalid session");
response.sendRedirect("/");
}
}
}
Here is my form posting. The form is actually submitted via javascript after I perform validation, I just merely call $('#files).submit(); not sure if that really matters or not.
<form id="files" name="files" method="POST" action="FileUpload" enctype="multipart/form-data">
The moment they post, the session is lost
Calling File Upload
Checking Session:null
null
Here is the start of the servlet
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("Calling File Upload");
HttpSession session = request.getSession(false);
System.out.println("Checking Session:"+session);
if(session != null){
Object projectId = session.getAttribute("projectId");
System.out.println("Accessing File Upload: Session is valid");
It's the same method all across the board. I have no idea what the problem is.
I've narrowed down the issue but I still have not resolved it yet. It happens during my redirect. I also was not encoding the URL correctly. I have modified all my redirects to have the folowing:
request.getRequestDispatcher(response.encodeRedirectURL("views/attachments.jsp")).forward(request, response);
This only resolves it on the server side though and does not provide a solution when I am handling redirects from the client.

changing URL but want to send data to controller

My web application has a new requirement that if parameter coming in url then land to email page. otherwise on index page like always.
Its a very old client product and not much scope to change lot in code so i put a check in controller that if encrypted email coming in then land to email page.
example url -
http://localhost:8080/R2/Controller?email=jAOtTv22BfkTkVrhTN/RHQ==
Everything works fine but i want to change URL.
How can i get rid of " /Controller " in URL but still it hits to controller.???
Controller code like -
public class Controller extends HttpServlet {
static Logger logger = Logger.getLogger(Controller.class);
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
// get the action property from the request
String theAction = request.getParameter("action");
String theSource = request.getParameter("s");
String theSource1 = request.getParameter("email");
String em ="";
Action action=null;
em = EncryptEmail.decrypt(theSource1,GFWConstants.BLOWFISH_KEY);
if (em.equals(""))
rd = request.getRequestDispatcher("index.jsp?emailRtv=0");
else
rd = request.getRequestDispatcher("email-preferences.jsp?emailRtv=2&emailAddress="+em);
rd.forward(request,response);
return;
}
Thanks in advance.
adding two url-pattern to web.xml file worked.

Java session filters with users and admin login

On my web application, i have 2 main sections
User
Admin
I am using java session filter to check for user session and allow access to specific part of the website. Hence user have access to only the user pages section and administrator have access to admin section.
The session filter for Users is already implemented and it works fine. it checks for user(username and password from database - mysql) and gives access to the restricted subfolder, where I've xhtml pages.
if i wanted filters to check for admin section authentication(admin username and password are stored in db) and allow them access based upon their user level.
do i need to create 1 more filter - admin?
currently here is my implementation for User:
package com.shadibandhan.ControllerLayer;
import java.io.IOException;
import java.util.ArrayList;
import java.util.StringTokenizer;
import javax.servlet.*;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.http.Cookie;
/**
*
* #author MUDASSIR
*/
public class SessionFilter implements Filter {
private ArrayList<String> urlList;
private String toGoTo = null;
private boolean userCookieExists = false;
#Override
public void init(FilterConfig config) throws ServletException {
System.out.println("****************************************");
System.out.println("***Session Filter Servlet initialized***");
System.out.println("****************************************");
String urls = config.getInitParameter("avoid-urls");
System.out.println("The urls to avoid are = " + urls);
StringTokenizer token = new StringTokenizer(urls, ",");
urlList = new ArrayList<String>();
while (token.hasMoreTokens()) {
urlList.add(token.nextToken());
}
}
#Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
System.out.println("This is the doFilter method");
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
String contextRelativeURI = null;
String contextRelativeURIForAdmin = null;
contextRelativeURI = request.getRequestURI().substring(request.getContextPath().length());
String contextPath = request.getContextPath();
String remoteHost = request.getRemoteHost();
String url = contextPath + contextRelativeURI;
System.out.println("-----------------> Servlet path is = " + contextRelativeURI);
System.out.println("-----------------> Context path is " + contextPath);
System.out.println("-----------------> URL is " + url);
System.out.println("-----------------> Remote Host is " + remoteHost);
boolean allowedRequest = false;
if (urlList.contains(contextRelativeURI)) {
allowedRequest = true;
}
if (!allowedRequest) {
HttpSession session = request.getSession(false);
if (null == session) {
System.out.println("Session is not present");
response.sendRedirect(contextPath);
return;
}
if (null != session) {
System.out.println("Session is present");
System.out.println("\nSession no. is = " + session.getId());
if (session.getAttribute("logged-in") == "true") {
System.out.println("Session logged-in attribute is true, " + session.getAttribute("sessionUsername") + " is logged in.");
RequestDispatcher dispatcher = request.getRequestDispatcher(contextRelativeURI);
dispatcher.forward(request, response);
return;
} else {
System.out.println("Session logged-in attribute is not true");
response.sendRedirect(contextPath);
return;
}
}
}
chain.doFilter(req, res);
}
#Override
public void destroy() {
}
}
This is my web.xml mapping for the filter
<filter>
<filter-name>SessionFilter</filter-name>
<filter-class>
com.shadibandhan.ControllerLayer.SessionFilter
</filter-class>
<init-param>
<param-name>avoid-urls</param-name>
<param-value></param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>SessionFilter</filter-name>
<url-pattern>/com.shadibandhan.Restricted/*</url-pattern>
</filter-mapping>
Now, do i put the admin pages in the restricted folder also ? or i put them in another separate folder ?
I also seen the servlet authentication method mentioned here which recommends changes in the tomcat-users.xml file but i've my usernames and passwords in the db.
Please suggest recommended methods.
Well, the best way of securing a web application is using the container managed authentication so your application doesn't need to handle the authentication and authorisation mechanism. That mechanism is called JAAS in the Java world.
Using the container managed authentication usually requires a bit of configuration on the servlet application - apart the changes required in your web application - but you'll be more secure. Since you said that you were using Tomcat then I will give you the best answer I can based on that servlet container, others are configured in a different way.
1. Configure the Tomcat Realm
Fist of all, forget about the tomcat-users.xml (it's insecure) and decide how you are going to store your authentication data, an LDAP server? a database? which database?. Once you have decided you will need to modify your server.xml file under conf folder in Tomcat to add a new realm. The type of realm to create will depend in your previous decision.
And let's state the obvious:Add users to the storage.
2. Configure the web application
You'll need now to configure the authentication method in your web application side. This is done modifying the web.xml file under /WEB-INF.
You may choose between Basic authentication or Form based authentication. I prefer using the latter as it allows me to provide with a customised form to the end users.
Some of the links I'm providing here describe the process step by step. They also include information regarding how to limit access to parts of your application to different kind of users, i.e.:
<security-constraint>
<web-resource-collection>
<web-resource-name>AdminPages</web-resource-name>
<description> accessible by authorised users </description>
<url-pattern>/admin/*</url-pattern>
<http-method>GET</http-method>
</web-resource-collection>
<auth-constraint>
<description>These are the roles who have access</description>
<role-name>ADMIN</role-name>
</auth-constraint>
</security-constraint>
3. Knowing the user
After all that configuration your application should be able to know the username by means of the getRemoteUser() method in HttpServletRequest.
EDIT:
I'd suggest to use same table for admins and users and just make the difference between them using roles. If your admin entity needs additional fields that shouldn't be available for regular users then link both tables and just deal with the admin one when HttpServletRequest.isUserInRole("ADMIN") returns true.

Configure tomcat to accept post request

How can I configure tomcat so when a post request is made the request parameters are outputted to a jsp file? Do I need a servlet which forwards to a jsp or can this be handled within a jsp file ?
Here is my method which sends the post request to the tomcat server -
public void sendContentUsingPost() throws IOException {
HttpConnection httpConn = null;
String url = "http://LOCALHOST:8080/services/getdata";
// InputStream is = null;
OutputStream os = null;
try {
// Open an HTTP Connection object
httpConn = (HttpConnection)Connector.open(url);
// Setup HTTP Request to POST
httpConn.setRequestMethod(HttpConnection.POST);
httpConn.setRequestProperty("User-Agent",
"Profile/MIDP-1.0 Confirguration/CLDC-1.0");
httpConn.setRequestProperty("Accept_Language","en-US");
//Content-Type is must to pass parameters in POST Request
httpConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
// This function retrieves the information of this connection
getConnectionInformation(httpConn);
String params;
params = "?id=test&data=testdata";
System.out.println("Writing "+params);
// httpConn.setRequestProperty( "Content-Length", String.valueOf(params.length()));
os = httpConn.openOutputStream();
os.write(params.getBytes());
} finally {
if(os != null)
os.close();
if(httpConn != null)
httpConn.close();
}
}
Thanks
First of all, your query string is invalid.
params = "?id=test&data=testdata";
It should have been
params = "id=test&data=testdata";
The ? is only valid when you concatenate it to the request URL as a GET query string. You should not use it when you want to write it as POST request body.
Said that, if this service is not supposed to return HTML (e.g. plaintext, JSON, XML, CSV, etc), then use a servlet. Here's an example which emits plaintext.
String id = request.getParameter("id");
String data = request.getParameter("data");
response.setContentType("text/plain");
response.setContentEncoding("UTF-8");
response.getWriter().write(id + "," + data);
If this service is supposed to return HTML, then use JSP. Change the URL to point to the JSP's one.
String url = "http://LOCALHOST:8080/services/getdata.jsp";
And then add the following to the JSP template to print the request parameters.
${param.id}
${param.data}
Either way, you should be able to get the result (the response body) by reading the URLConnection#getInputStream().
See also:
How to use URLConnection to fire and handle HTTP requests?
Unrelated to the concrete problem, you are not taking character encoding carefully into account. I strongly recommend to do so. See also the above link for detailed examples.
A servlet can handle both get and post request in following manner:
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//remaning usedefinecode
}
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
If you have a tomcat installation from scratch, don't forget to add the following lines to web.xml in order to let the server accept GET, POST, etc. request:
<servlet>
<servlet-name>default</servlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
...
<init-param>
<param-name>readonly</param-name>
<param-value>false</param-value>
</init-param>
...
</servlet>

Categories