Search code examples
javajspjasperserver

Is it possible to indicate that the web session will be valid for a single site (or page)?


Let me explain myself well. I'm integrating my application with Jasper Report Server and I'm preventing the username and password from being sent via URL (with GET) to view a report.

For that I'm using a rest_v2 service for autenticate the user with a POST request and using the response body with the JSESSION to redirect the request to the Jasper Report (this time the site will not redirect to the login site because I got a valid session token).

What I want to do is limit the sites in which that session will be available, I only want it to be valid for the report page and that if the user tries to access the repository, then the session will not be available and the webpage redirects to the jasper login screen

Example: User request for a report which can be accesed in the url

/jasperserver/flow.html?_flowId=viewReportFlow&_flowId=viewReportFlow&ParentFolderUri=%2FReports&reportUnit=%2FTest%2FJasper_Report

If the user tries to go here outside of this URL, then the session will not be valid anymore.

Here is my source

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {      
    HttpPost post = new HttpPost("http://localhost:8080/jasperserver/rest_v2/login");
    
    int coderes;
    String username = request.getParameter("username");
    String pass = request.getParameter("pass");
    
    List<NameValuePair> urlParameters = new ArrayList<>();
    urlParameters.add(new BasicNameValuePair("j_username",username));
    urlParameters.add(new BasicNameValuePair("j_password",pass));
    
    post.setHeader("type", "POST");
    post.setHeader("cors", "true");
    post.setHeader("contentType", "application/x-www-form-urlencoded");
    post.setHeader("secure","true");
    
    post.setEntity(new UrlEncodedFormEntity(urlParameters));    
    
    Header[] headers = null;
    
    try(CloseableHttpClient client = HttpClients.createDefault();
            CloseableHttpResponse chres = client.execute(post)){    
        StatusLine status = chres.getStatusLine();
        coderes = status.getStatusCode();
        headers = chres.getAllHeaders();
    }
    
    if(coderes == 200) {
        for(int i = 0; i < headers.length; i++) {
            if(headers[i].getName().equals("Set-Cookie")) {
                response.addHeader(headers[i].getName(), ServletUtils.setCookieValue(headers[i].getValue().split(";"), "/jasperserver/flow.html?_flowId=viewReportFlow&_flowId=viewReportFlow&ParentFolderUri=%2FPublished&reportUnit=%2FPublished%2FUser_Report&standAlone=true"));
            } else {
                response.addHeader(headers[i].getName(), headers[i].getValue());
            }
        }
        response.sendRedirect("http://localhost:8080/jasperserver/flow.html?_flowId=viewReportFlow&_flowId=viewReportFlow&ParentFolderUri=%2FPublished&reportUnit=%2FPublished%2FUser_Report&standAlone=true");
    } else {
        response.getWriter().println("Incorrect Credentials");
    }
}

The setCookieValue method

public static String setCookieValue(String[] attr, String requestUrl) {
    Date targetTime = Calendar.getInstance().getTime();
    
    SimpleDateFormat fmt = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss");
    
    targetTime = DateUtils.addMinutes(targetTime, 5);
            
    StringBuilder sb = new StringBuilder();
    for(int i = 0; i < attr.length; i++){
          if(attr[i].contains("userLocale")){
              attr[i] = "userLocale=es_ES";
          }else if(attr[i].contains("Expires")) {
              attr[i] = "Expires=" + fmt.format(targetTime) + " GMT";
          }else if(attr[i].contains("Path")){
              attr[i] = requestUrl;
          }
          sb.append(attr[i]).append(";");
    }
    return sb.toString();
}

In this method what I try to do is to put the requested URL in the attribute Path, because what I understood from this site:

This method gets the path to which this cookie applies.

Maybe I'm typing the URL wrong or I'm using the wrong attribute.

I feel that it's possible


Solution

  • Theoretically you can manipulate the cookie of the Java HTTP session (it works at least for Tomcat and Spring Boot). Setting the session cookie Tomcat makes it accessible over the HttpServletResponse instance. You can overwrite JSESSION cookie replacing the Path attribute.

    But such a manual manipulation is not covered by JEE standard and it will be really painful to debug this solution.

    I have a better idea! Is Jasper Report Server embedded in your application as a third party servlet? If yes, I would suggest to wrap a custom filter around this Servlet. The filter can be specified in "web.xml". Inside the filter you need to create a proxy for HttpServletRequest and inject any authentication information you want. You can emulate anything on this level including a fake HTTP session.