When I visit my page .../index.jsp while having no HttpSessions, index.jsp still creates the JSESSIONID-cookie. Even worse, in the servlet responsible for logging people out, session.invalidate() does not seem to fix the issue.
index.jsp looks like this:
<%#page import="javax.servlet.http.Cookie"%>
<%#page contentType="text/html" pageEncoding="utf-8"%>
<%#page session="true"%>
<%!
void removeJSessionIdCookie(HttpServletResponse response) {
Cookie cookie = new Cookie("JESSIONID", "");
cookie.setValue(null);
cookie.setMaxAge(0);
cookie.setPath("/");
response.addCookie(cookie);
}
%>
<%
if (session != null) {
out.print("Session not null.");
if (session.getAttribute(Config.CURRENT_USER_ATTRIBUTE) != null) {
out.print("have user");
request.getRequestDispatcher("app.jsp").forward(request, response);
return;
} else {
out.println("no user here");
session.invalidate();
removeJSessionIdCookie(response);
}
}
%>
<html>...</html>
If you have session="true" in your <%#page%> directive, then the JSP framework code always creates a new session if the calling client does not bring a session cookie, i.e. has no session yet.
You need to put session="false" in to the page directive; this makes the Framework stop creating sessions for you.
Related
I am trying to pass an attribute from a java servlet to jsp and write this attribute on jsp file. However it does not redirect to jsp file url but it writes the content of the jsp file. Here is my related codes:
Control.java:
#WebServlet("/Control")
public class Control extends HttpServlet{
#Override
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Key key = MacProvider.generateKey();
long time = System.currentTimeMillis();
try{
String jwt = Jwts.builder()
.signWith(SignatureAlgorithm.HS256, key)
.setSubject("username")
.setIssuedAt(new Date(time))
.setExpiration(new Date(time+6000000))
.claim("password","password")
.compact();
req.setAttribute("jwt", jwt);
req.getRequestDispatcher("/Home.jsp").forward(req,resp);
}catch (Exception e){
e.printStackTrace();
}
}
}
Home.jsp:
<%# page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Welcome</title>
</head>
<body>
${jwt}
</body>
</html>
Here, browser stays on http://localhost:8080/Control but it writes the content of Home.jsp file which is just a java web token result string.
2) My second question is when I tryed to store this jwt result string in browser local storage and then write it in jsp file in order to check if it stored in browser or not. But it does not prints anything. To do this, I just changed the Home.jsp file as follow:
(I took both of the code snippets from here)
Home.jsp:
<%# page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Welcome</title>
</head>
<body>
<script>
localStorage.setItem("jwt", ${jwt});
console.log(localStorage.getItem("jwt"));
var jjwt = localStorage.getItem("jwt");
document.write(jjwt);
</script>
</body>
</html>
Another try:
<html>
<head>
<script>
function myFunction() {
localStorage.setItem("jwt", ${jwt});
console.log(localStorage.getItem("jwt"));
var jjwt = localStorage.getItem("jwt");
document.getElementById("myText").innerHTML = jjwt;
}
</script>
</head>
<body onload="myFunction()">
<span id="myText"></span>
</body>
</html>
Where am I doing wrong?
1) When you use RequestDispatcher.forward(request,response), your servlet will still have control but your jsp page will be loaded so this is nothing to worry about.
If you want your browser URL to show your JSP page URL, do response.sendRedirect("URL TO LOAD");
2)Since you are using JSP, try accessing the request variables like below and print it
<% String jwt = (String) request.getAttribute("jwt");%>
We need to set it as
localStorage.setItem('jwt', <%=jwt%>);
In my login servlet, the last code of doPost is as follows:
HttpSession session = request.getSession();
session.setAttribute(Config.CURRENT_USER_PARAMETER, user);
request.getRequestDispatcher("app.jsp").forward(request, response);
What comes to app.jsp, it is as follows:
<%#page import="fi.vakuutustiedot.controllers.Config"%>
<%#page import="fi.vakuutustiedot.model.User"%>
<%#taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%#page contentType="text/html" pageEncoding="UTF-8"%>
<%
if (session == null) {
request.getRequestDispatcher("index.html").forward(request, response);
return;
}
User user = (User) session.getAttribute(Config.CURRENT_USER_PARAMETER);
if (user == null) {
session.invalidate();
request.getRequestDispatcher("index.html").forward(request, response);
return;
}
%>
<!DOCTYPE html>
...
My problem is the following scenario:
I login through the HTML form that is connected to my login servlet.
The login servlet creates a HttpSession and adds an attribute for the object describing the user in question.
Finally, it forwards to app.jsp.
The problem is that when I am logged and forwarded to app.jsp, I see everything I am supposed to see, but if I type .../app.jsp in the location bar and press Enter it redirects to index.html! However, when I visit app.jsp the second, third, .etc time, everything is fine and no spurious redirect to index.html happens.
Is this solution adequate from the security standpoint?
I resolved the issue by adding in the login servlet the following line:
HttpSession session = request.getSession();
request.setAttribute(Config.CURRENT_USER_PARAMETER, user); // <- The new added line.
session.setAttribute(Config.CURRENT_USER_PARAMETER, user);
request.getRequestDispatcher("app.jsp").forward(request, response);
And in app.jsp I have:
<%#page import="fi.vakuutustiedot.controllers.Config"%>
<%#page import="fi.vakuutustiedot.model.User"%>
<%#page import="fi.vakuutustiedot.model.UserType"%>
<%#taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%#page contentType="text/html" pageEncoding="UTF-8"%>
<%! User user = null; %>
<%
if (session == null) {
request.getRequestDispatcher("no_session.html").forward(request, response);
return;
}
user = (User) session.getAttribute(Config.CURRENT_USER_PARAMETER);
if (user == null) {
user = (User) request.getAttribute(Config.CURRENT_USER_PARAMETER);
}
if (user == null) {
request.getRequestDispatcher("test.jsp").forward(request, response);
return;
}
%>
<!DOCTYPE html>
...
Answering my own question
In the login servlet, all I do is:
HttpSession session = request.getSession();
session.setAttribute(Config.CURRENT_USER_PARAMETER, user);
response.sendRedirect("app.jsp");
That way, the user object is available straight from the session and I do not need to put that user to the request object.
It would seem you are trying to get to a page outside of your context.
By your question, I am only guessing your directory is:
/index.html
/app.jsp
When you are running your application, you probably inter a URI such as:
http://[my_server]/[my_app]/index.html
or just:
http://[my_server]/[my_app]/
When you type ../app.jsp, your are trying to get something that is not there. Your server is probably set to send a default page of index.html with no default error page.
I am guessing you are just getting back the index.html page because of the incorrect URI.
I have given a session timeout of 1 minute in my application's web.xml :
<session-config>
<session-timeout>1</session-timeout>
</session-config>
I am also checking at each and every step whether the servlet or jsp is preventing auto generation of new session on its own.
e.g.
In each and every jsp file I am giving following sets of instructions to prevent autogeneration :
<%# page session="false"%>
<%#page isELIgnored="false" %>
And in the corresponding servlet of every jsp file, I am authenticating the session as follows :
RequestDispatcher dispatcher;
HttpSession httpSession = request.getSession(false);
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP
response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
response.setDateHeader("Expires", 0); // Proxies.
if (httpSession == null) {
dispatcher = request.getRequestDispatcher("/WEB-INF/view/sessionexpire.jsp");
dispatcher.forward(request, response);
} else {
// collecting the parameters from front end...
Still it is auto generating a new session even at the expiry of current session.
I have written a debug statement in my application that checks for the flaw :
System.out.println("session id : " + httpSession.getId());
The above statement prints a new session id if the page is reloaded despite session expiration.
What I want, is that once the session gets expired, the corresponding page in my iframe should display the message of session expiration and user must be forced to relogin.
But what it does instead is that when i re-click on the link, it opens the same web page with a brand new session.
I have also placed a HttpSessionListener that does some cleaning job for me.
public class InsightHttpSessionListener implements HttpSessionListener {
#Override
public void sessionCreated(HttpSessionEvent arg0) {
}
#Override
public void sessionDestroyed(HttpSessionEvent arg0) {
InsightDbConn insightDbConn = InsightDbConn.getInstance();
HttpSession httpSession = arg0.getSession();
insightDbConn.getFeatureIds().clear();
System.out.println("feature ids list clear");
}
I really dont know what went wrong. Please explain where I am leaving the flaw and session is regenerating by its own.
I am learning JSP. I am not able to find out how sessions got created in JSP.
what I know till now is session is implicit object creates under _jspService method. So I manually created session. In below JSP code I created session same as it automatically creates in index_jsp but i am getting value as null. So any body can explain me why I am getting null?
<%# page import ="java.util.*" session="false" %>
<%
javax.servlet.http.HttpSession session = null;
session = pageContext.getSession();
%>
<html>
<body>
<%=session %>
</body>
As you said:
session is implicit object created under _jspService method
The JSP file is compiled by the Jasper Engine to a java class. Despite of the code you have writen in the JSP, in the created Java class there are some preparation of these implicit objects.
Therefore you don't need to do it again.
You can just use them. You can write in your JSP the code:
From EL:<br>
sessionScope.name: ${sessionScope.name}<br>
<br>
From Scriptlet. <br>
<%=session.getAttribute("name")%>
And you get the same output twice: the value of the session attribute "name".
In example of a JSP with content:
<%# page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Title</title>
</head>
<body>
From EL:<br>
sessionScope.name: ${sessionScope.name}<br>
<br>
From Scriptlet. <br>
<%=session.getAttribute("name")%>
</body>
</html>
Will result in a java class file:
package org.apache.jsp;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
public final class testcompile_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent {
private static final JspFactory _jspxFactory = JspFactory.getDefaultFactory();
private static java.util.List<String> _jspx_dependants;
private org.glassfish.jsp.api.ResourceInjector _jspx_resourceInjector;
public java.util.List<String> getDependants() {
return _jspx_dependants;
}
public void _jspService(HttpServletRequest request, HttpServletResponse response)
throws java.io.IOException, ServletException {
PageContext pageContext = null;
HttpSession session = null;
ServletContext application = null;
ServletConfig config = null;
JspWriter out = null;
Object page = this;
JspWriter _jspx_out = null;
PageContext _jspx_page_context = null;
try {
response.setContentType("text/html; charset=UTF-8");
response.setHeader("X-Powered-By", "JSP/2.3");
pageContext = _jspxFactory.getPageContext(this, request, response,
null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
_jspx_resourceInjector = (org.glassfish.jsp.api.ResourceInjector) application.getAttribute("com.sun.appserv.jsp.resource.injector");
out.write("\r\n");
out.write("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\r\n");
out.write("<html>\r\n");
out.write("<head>\r\n");
out.write("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\r\n");
out.write("<title>Title</title>\r\n");
out.write("</head>\r\n");
out.write("<body>\r\n");
out.write("From EL:<br>\r\n");
out.write("sessionScope.name: ");
out.write((java.lang.String) org.apache.jasper.runtime.PageContextImpl.evaluateExpression("${sessionScope.name}", java.lang.String.class, (PageContext)_jspx_page_context, null));
out.write("<br>\r\n");
out.write("<br>\r\n");
out.write("From Scriptlet. <br>\r\n");
out.print(session.getAttribute("name"));
out.write("\r\n");
out.write("</body>\r\n");
out.write("</html>");
} catch (Throwable t) {
if (!(t instanceof SkipPageException)){
out = _jspx_out;
if (out != null && out.getBufferSize() != 0)
out.clearBuffer();
if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
else throw new ServletException(t);
}
} finally {
_jspxFactory.releasePageContext(_jspx_page_context);
}
}
}
As you can see in the _jspService method there are lines:
HttpSession session = null;
...
session = pageContext.getSession();
Basically this is the implicit session object. Your code follow after that and can use it.
EDIT:
With <%# pagesession="false" %> you say "i don't need the session". So the session is not bond in the pageContext. Therefore you if you call pageContext.getSession() you receive null;
If you need it you have to use:
request.getSession();
Can explain me why I am getting null for session ?
The session in the JSP file will be disabled if you set the session attribute to false i.e., session="false", you can look here for more details.
I am not able to find out how sessions got created in JSP.
httpsession object will be created (& maintained) by the servlet container when you invoke request.getSession(true); from JSP (because request is also an implicit object in JSP).
public HttpSession getSession(boolean create) : Returns the current
HttpSession associated with this request or, if there is no current
session and create is true, returns a new session. If create is false
and the request has no valid HttpSession, this method returns null.
You can refer the API here
So, to create the session from your code you change it as:
<%
javax.servlet.http.HttpSession session = request.getSession(true);
// you can session object from now add attributes,
// get attributes, remove attributes, etc..
%>
Also, once the session is created (as shown above using request.getSession(true)), you need to use request.getSession() to retrive the same session object.
In other words, in your whole application,
(1) Create the session ONLY ONCE during the user login time in LoginServlet or LoginController class using request.getSession(true)
(2) And then use request.getSession() in all other servlet/controller methods.
As a side note, I strongly suggest you to use Controller (like using Spring) or Servlet classes to write the Java code because JSP is meant only for the presentation layer (to display the html content).
I want to send data to controller action and I want to get value from action. But I cannot send value and I cannot convert value getting from controller to boolean, string etc..
contact =(List)response.sendRedirect("contact/login.action");
My contactController's login.action is below: (Also, I tried the boolean function)
#RequestMapping(value="/contact/login.action")
public #ResponseBody Map<String,? extends Object> login(#RequestParam Object data) throws Exception {
try{
List<Contact> contacts = contactService.login(data);
return getMap(contacts);
} catch (Exception e) {
}
return null;
}
My jsp codes are below:
<%#page import="com.loiane.web.ContactController"%>
<%#page import=" com.loiane.model.Contact"%>
<%#page import="java.util.List"%>
<%# page language="java" pageEncoding="UTF-8"%>
<%
String result;
List<Contact> contact;
String loginUsername = request.getParameter("loginUsername");
String loginPassword = request.getParameter("loginPassword");
contact =(List)response.sendRedirect("contact/login.action");
out.println(request.getAttribute("message"));
if ((null != loginUsername && loginUsername.length() > 0) && (null != loginPassword && loginPassword.length() > 0)) {
if (contact.size()>0)
result = "{success:true}";
else
result = "{success:false,errors:{reason:'Login failed.Try again'}}";
} else {
result = "{success:false,errors:{reason:'Login failed.Try again'}}";
}
%>
<%=result %>
Rather than doing response.sendRedirect to your servlet from JSP, your form should have the servlet as its action.
<form action='contact/login.action' method='post'>
Your servlet needs to implement doPost. Having just a method called login will not work.
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
Your JSP should be the login form that sends to the servlet (via HTML, when you click submit, not via JSP code) and the servlet should do ALL of the login stuff, including the request.getParameter calls.
Then if there is a login error, the servlet should response.sendRedirect to the login form jsp.
And please note that response.sendRedirect actually sends the browser to another page. Thus it will never return a list or any other datatype.
And you would be better off not using scriptlets in your JSP. You can do everything in the servlet. Just use the jsp like a HTML page.