I have a JSP, Servlet, Hibernate application. In this application I have a very weird problem. That is, if the session got expired (in other words "time out") and when the user click on a link the page will be redirected to the index page, but after that the user is not able to log in and access the last link he clicked. I will describe it step by step in below.
User log into the application. Session get created.
He access the path /Passport
User is now idle, session get expired.
User come back and click on link to access /Visa . Since the session is now idle, user will be redirected to index page.
User log in.
Click on the link to access /Visa (from anywhere where the link is available)
. The link is an where it links to its path like
Visa?idEmployee=1
Now the problem. User is redirected back to index page.
I have Filter to monitor whether the session is null and whether the required session attributes are not null. If the request do not fulfill the mentioned 2 conditions, the request will be sent back to the index.
The filter code is below.
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package Filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
*
* #author user
*/
public class AuthenticationFilter_Level1 implements Filter
{
#Override
public void init(FilterConfig filterConfig) throws ServletException
{
}
#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);
Integer attribute = null;
if(session!=null && session.getAttribute("idSubUser")!=null)
{
chain.doFilter(req, res);
}
else
{
//response.sendRedirect("index.html");
RequestDispatcher dispatch = request.getRequestDispatcher("index.html");
dispatch.forward(req, res);
}
}
#Override
public void destroy()
{
}
}
In web.xml, I have added the filter from servlet to servlet, like below.
<filter-mapping>
<filter-name>AuthenticationFilter_Level1</filter-name>
<url-pattern>/RegSrvlt</url-pattern>
<url-pattern>/AdminPopulateSrvlt</url-pattern>
<url-pattern>/AgentPopulate</url-pattern>
......
Filter session timeout is configured as below.
<session-config>
<session-timeout>
1
</session-timeout>
</session-config>
So, what is happening here?
Update
When the above error happens, the URL actually looks like http://localhost:8080/xxx/Visa?idEmployee=1 even though it is redirected!
UPDATE
I found this has no connection with the filter. Then what can make this?
else
{
if (session != null) {
session.invalidate();
}
...
And check the where sessions are created (i.e. public JSPs/servlets).
Another possible cause could be a problem of caching in browser :
client browser asks for /Visa
server sends index.html => browser caches it as it is a nice html page
...
on same browser session, user clicks on a /Visa links
without even asking anything to server, browser displays cached index.html page
How do confirm :
server side, by looking the server logs to see if the page was actually requested
client or server side by using a network spy such as wireshark and look if a request is sended
client side by emptying the cache and not the cookies
How to fix :
try to add a header asking not to cache the page before forwarding to index.html - it should be possible but I do not exactly know the proper header configuration
replace the forward to index.html with a redirection. That way the browser should not cache index.html for the /Visa URL
Related
I read that to persist session in servlet a cookie gets saved at client side with the name of JSESSIONID.I checked it also and I found the cookie of localhost with the name of JSESSIONID with some random String value.
So I tried to create the session manually by creating the JSESSIONID cookie in the servlet but when I am trying to get the session it's not working.
What is happening here?
Is there anything else other than cookie(JSESSIONID) that gets stored soomewhere for the session creation? If not why I'm not able to get the session ?
Please Help.
Code that I used to create the cookie and get the session
package sessionHandling;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
#WebServlet("/sessionhandling")
public class SessionHandling extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletOutputStream out = response.getOutputStream();
out.print("Hello Mr.! How are you?");
HttpSession session = request.getSession(false);
if(session != null){
out.println("You are logged in.");
out.println("session found with "+session.getId());
out.println("session found with "+session.getLastAccessedTime());
}else{
//session = request.getSession(true);
Cookie JSESSIONID = new Cookie("JSESSIONID", "12345");
JSESSIONID.setMaxAge(-1);
response.addCookie(JSESSIONID);
System.out.println("Cookie Created");
out.print("You are not logged in");
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
You're not responsible for creating or tracking the cookie. The servlet container looks after this for you.
As soon as you invoke:
HttpSession session = request.getSession(true);
or
HttpSession session = request.getSession();
then the servlet container will start maintaining the session for you (and generate the cookie as needed).
The HttpSession object is maintained in server memory between requests and is usually looked up by the session id. If you create the cookie yourself the server will not know anything about it or any associated HttpSession.
Once you run your code , first time , session will be null and you will instruct the browser (or any other client) to create the JESSIONID cookie. Till here it is all correct.
Now, when you make the request again, browser (or any other client) will attach the cookie to the request and tomcat (or any other servlet engine) will receive the JESSIONID. Till here it is all fine.
But what now ? Tomcat (or any other servlet engine) will then search if it has any HttpSession object having sessionID "12345". Do you think it will be found ? No.
Why ? The code that you wrote above was only to Set cookie header in response message. It did not instructed tomcat(or any other servlet engine) to view this JSESSIONID named cookie as a session Id and create a corresponding HttpSession Object internally in Java Heap.
That's why we use request.getSession(). It instructs tomcat to do 2 things -
Whatever you did i.e. add the Set Cookie info in response by name JSESSIONID with a random ID.
Creates a corresponding HttpSession object and save it in memory (by default), so that next time when request comes, it can recognise that JESSIONID as a valid session ID by finding a corresponding HttpSession object. This was missed by your code.
I am writing several web applications based on both spring security and the spring security saml extension (RC2).
I have single sign on working with multiple service providers and an Identity provider in a basic fashion (based off the example defined in the spring saml docs).
When the user accesses a protected resource on the SP, he is forwarded to a protected resource on the IDP. So because the user isn't logged in yet, they are redirected to a login page (standard spring security stuff). After logging in, the original request is played back and the authNRequest/Response is done and the user is redirected to the original secured resource.
I now have a requirement that ensures that all services providers must ask the identity provider whether the user is logged in before each request (instead of doing it locally at the SP).
It is my understanding that a local (SP) and remote (IDP) security context is stored and queried during each request and if there isn't a valid context, the user is then forwarded to the identity provider to go through the auth process.
So my question is, is there a way I can configure saml/spring security on the SP side to always "ping" or ask the IDP to check if the current user is logged in or is this sort of thing unnecessary/unsupported.
thanks in advance
You are right, Spring SAML queries the local security context during each request and forwards user to IDP once it becomes invalid.
The typical mechanism which defines when the context becomes invalid is usage of SAML's attribute SessionNotOnOrAfter. The attribute is included inside the Assertion's AuthenticationStatement sent back from IDP. Spring SAML will automatically re-authenticate the user once the time goes beyond the value provided in the SessionNotOnOrAfter.
In case you would like to re-authenticate on every request, you could for example add a new custom filter similar to this:
package fi.test;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.FilterInvocation;
import org.springframework.web.filter.GenericFilterBean;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;
public class ReAuthenticateFilter extends GenericFilterBean {
private static final String FILTER_APPLIED = "__spring_security_filterReAuthenticate_filterApplied";
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
FilterInvocation fi = new FilterInvocation(request, response, chain);
invoke(fi);
}
protected void invoke(FilterInvocation fi) throws IOException, ServletException {
if ((fi.getRequest() != null) && (fi.getRequest().getAttribute(FILTER_APPLIED) != null)) {
fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
} else {
if (fi.getRequest() != null) {
fi.getRequest().setAttribute(FILTER_APPLIED, Boolean.TRUE);
}
}
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
try {
fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
} finally {
if (authentication != null) {
authentication.setAuthenticated(false);
}
}
}
}
You would then include the filter in your Spring configuration:
<security:http entry-point-ref="samlEntryPoint">
<security:custom-filter after="SECURITY_CONTEXT_FILTER" ref="reAuthenticateFilter"/>
...
</security:http>
<bean id="reAuthenticateFilter" class="fi.test.ReAuthenticateFilter"/>
Re-authenticating on every request is rather expensive operation (a round-trip to the IDP through user's browser) and is likely to result in poor responsiveness of the application.
I'm using SimpleCaptcha to secure our contact form. It works well, but only after reloading the page.
The Servlet is nl.captcha.servlet.StickyCaptchaServlet, so it should not change the image after reloads. But when first opening the page the image is just not loaded. However, after reloading everything works fine.
the web.xml
The captcha is served by an application running at /services.
<web-app>
<servlet>
<servlet-name>captcha</servlet-name>
<servlet-class>nl.captcha.servlet.StickyCaptchaServlet<servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>captcha</servlet>
<url-pattern>/captcha.png</url-pattern>
</servlet-mapping>
</web-app>
the html
<img src="/services/captcha.png">
the server
I'm using tomcat-7.0.34 on a Windows 7 64bit machine with Java 1.7.0_07.
the question
Why does the image only show up after a reload? Any ideas?
there are several steps you can follow:
1> modify web.xml add your servlet that extends nl.captcha.servlet.StickyCaptchaServlet class
<servlet>
<description></description>
<display-name>CustomCaptchaServlet</display-name>
<servlet-name>CustomCaptchaServlet</servlet-name>
<servlet-class>org.example.servlets.CustomCaptchaServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CustomCaptchaServlet</servlet-name>
<url-pattern>/CustomCaptchaServlet</url-pattern>
</servlet-mapping>
2> CustomCaptchaServlet.java
package org.example.servlets;
import static nl.captcha.Captcha.NAME;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import nl.captcha.Captcha;
import nl.captcha.servlet.CaptchaServletUtil;
import nl.captcha.servlet.StickyCaptchaServlet;
public class CustomCaptchaServlet extends StickyCaptchaServlet {
private static final long serialVersionUID = 1L;
/**
* #see StickyCaptchaServlet#StickyCaptchaServlet()
*/
public CustomCaptchaServlet() {
super();
// TODO Auto-generated constructor stub
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String _width = getServletConfig().getInitParameter("width");
String _height = getServletConfig().getInitParameter("height");
HttpSession session = request.getSession();
Captcha captcha;
if (session.getAttribute(NAME) == null) {
captcha = new Captcha.Builder(Integer.parseInt(_width), Integer.parseInt(_height))
.addText()
.gimp()
.addBorder()
.addNoise()
.addBackground()
.build();
session.setAttribute(NAME, captcha);
CaptchaServletUtil.writeImage(response, captcha.getImage());
return;
}
captcha = (Captcha) session.getAttribute(NAME);
CaptchaServletUtil.writeImage(response, captcha.getImage());
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
Just do this way to by pass what emka86 had said.
<img src="/services/captcha.png" style="display:none"> (Duplicate part to fix the issue)
<img src="/services/captcha.png"> (The actual one)
Hope this helps for any future developer out there.
Check that the web.xml has captcha.png while the HTML is referring to captcha.jpg.
Does that solve the issue?
The problem is that StickyCaptchaServlet is creating new captcha image for session. When you make initial request to a page you have no session id so StickyCaptchaServlet cannot connect you to any image created for a particular session. After first request main servlet create session for you and send you back some kind of sessionId. With next request (also reload) you send to server request with recevied previously sessionId so now your StickyCaptchaServlet is possible to collect captcha image for your session because it knows that you are in any session.
Do you understand this explanation? Will it be helpfull for you?
Added after your question to resolve this problem.
You can add to your web app class which will implements HttpSessionListener. Then, in method sessionCreated you can add request to StickyCaptchaServlet with just created sessionId. According to StickyCaptchaServlet doc You just have to invoke doGet method of it with passed sessionId key. After that - when browser on your page will request for url /services/captcha.png it should get as response image created and prepared just before it by your HttpSessionListener implementation.
Other way is to use cliend side scripting and after page is loaded, with no image at all, just reload it - as this internal reload, for example JavaScript, the browser will know sessionId and will pass it through the request for captcha image. By reload I mean only reload image, not the whole page.
Will any of those suggestions resolve your problem? Give me a feedback about it.
I’m working on a grails web application with spring security. I have a requirement for forcing a session expiration after a fixed set of time even if the session is active.
I think I can add filter and check for each request's last login time:
if (CURRENT_TIME - LAST_LOGIN > ABSOLUTE_SESSIO EXPIRATION) then FORCE LOGOUT
But the problem is that the session is still active on the server until the user makes request.
Is this possible to destroy session immediately after N minutes even if user is using the system?
I was researching tomcat session management and how spring security handles it, but didn’t find any useful information.
Could anybody point me at some example? Has anybody implemented something similar?
[Edit: An idea for killing the session at a specific time decided by the login time would be use a task scheduler like Quartz to schedule a task that is passed the session as a parameter. You could then schedule it to call a job that performs a session.invalidate() at a specific point in time. The task would be scheduled at login time.]
This is how I would do it, but it doesn't kill the session at the specific time you want. It relies on the user making a request. It's not fool proof, but you could make the application poll the site every minute or so via an AJAX call perhaps.
Set a session activation time on the users session. Then add a filter to the web application for all incoming requests that checks the (activation period + the allowed time) exceeds the current time. If it does not, then call session.invalidate();
i.e. on login
HttpSession session = request.getSession();
session.setAttribute( "activation-time", System.currentTimeMillis() );
Then add a filter to web.xml
<filter>
<filter-name>SessionFilter</filter-name>
<filter-class>com.something.SessionFilter</filter-class>
<init-param>
<param-name>max-period</param-name>
<param-value>60000</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>SessionFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
The filter would be something along the lines of...
package com.something;
import java.io.IOException;
import java.util.Date;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
public class SessionFilter implements Filter {
private long maxPeriod;
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpSession session = request.getSession( false );
if ( session != null ) {
long activated = (long) session.getAttribute( "activation-time" );
if ( System.currentTimeMillis() > ( activated + maxPeriod ) ) {
session.invalidate();
}
}
chain.doFilter(req, res);
}
public void init(FilterConfig config) throws ServletException {
//Get init parameter
if ( config.getInitParameter("max-period") == null ) {
throw new IllegalStateException( "max-period must be provided" );
}
maxPeriod = new Long( config.getInitParameter("max-period") );
}
public void destroy() {
//add code to release any resource
}
}
If you need to invoke something when the session is invalidated then you can write a HttpSessionListener and configure in web.xml also.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Prevent user from going back to the previous secured page after logout
I was wondering how to invalidate session in JSP and servlets. In my website a person when logs-out reaches the login page but on clicking back button he can access the previous page. I am not able to understand where to put session.invalidate()
And further where should i invalidate it, on login.jsp or my other web pages when a person hits logout.
My filter class:-
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.annotation.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("currentSessionUser") == null) {
response.sendRedirect("Loginpage.jsp"); // No logged-in user found, so redirect to login page.
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
response.setDateHeader("Expires", 0);
} else {
chain.doFilter(req, res); // Logged-in user found, so just continue request.
}
}
}
In web.xml i've written :-
<filter>
<filter-name>loginFilter</filter-name>
<filter-class>LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>loginFilter</filter-name>
<url-pattern>/ARMS/*</url-pattern>
</filter-mapping>
On my Loginpage.jsp i've just written
<%
session.invalidate();
%>
Is it okay? Secondly I am not clear on directory structure. I am putting screen shots of it..
I am using apache tomcat 5.5 server, so i guess I should not put url-pattern annotation in filter class right? because it is only supported in tomcat 7 and above.
Invalidate the session in the servlet or the JSP that you go to when a user hits "log out".
In a crude way, you can check if a session exists on each page that a user goes.
Take a look at this thread, it has some answers that you are looking for.
http://forums.devx.com/showthread.php?t=146975
I use a servlet for the sole purpose of log outs. When a user hits the log out button it directs them to that page, which in turn checks for an active session and if it finds one, calls session.invalidate() then redirects the user back to the home page (or wherever you would like).
HttpSession session = request.getSession(false);
if(session != null){
session.invalidate();
RequestDispatcher rd = request.getRequestDispatcher("Loginpage.jsp");
rd.forward(request, response);
} else {
//There is no session. Redirect somewhere
}
This is just a quick example.