I have a webservice that does quite simple a forward to another webapp located on the same Tomcat container.
private Response forward(
#Context ServletContext context,
#Context HttpServletRequest request,
#Context HttpServletResponse response){
ServletContext ctx = context.getContext("/myothewebapp");
RequestDispatcher dispatcher=ctx.getRequestDispatcher("/test");
dispatcher.forward(request, response);
return Response.ok("").build();
}
This works as desired except the fact, that the sessions of this webapp are not being expired. In the tomcat manager you can see, that the opened sessions get accumulated quite fast, up to several hundreds of them.
I am not sure why they last when the response is already sent.
Any ideas what is missing in my forward-method?
Why they last when the response is already sent.
Why you think that session will be invalidated after response will be sent.
It will only be invalidated if session timeout occurs or you forcefully invalidate the session using :
Session#invalidate() method
Related
My question is simple - how to implement login-logout in servlet jsp?
Following is the use case...
I have a users table in DB with email,username and password
I have a mapped bean object - User in java having email,username,password properties
Simply I want to login by validating email and password BUT
Once I login and then logout, when I click on back button, it should not retain the session.
It should not give any warning BUT simply should ask for login
If I copy-paste restricted resource's link, it should ask for login
What all solutions I've gone through...
Some say to implement tomcat security using roles and bla bla... BUt I think I should not set username, passwords in some tomcat config file. Bcz the details are in DB table
Some ask to implement no-cache, pragma bla bla... but never work
Back button disable is foolish thing
**
What Help I am expecting from you guys ...?
**
Is there any third-party API available to do this?
How things are implemented in production ready applications ?
Should I use JAAS, or any other security process for exactly above mentioned scenario OR WHAT
Please give me some hint or solution how I should proceed implementing production ready login-logout in servlet-jsp
I've searched on internet but end up with simple Login examples or tomcat security roles etc. No one gives the actual solution. ANd please don't say that this question is NOT RELATED TO this FORUM.
Thanks
This happens because browser caches the web pages that are being loaded,you can prevent it by using filters and telling browser not to cache the web pages like below.
doFilter method of Filter
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", 0);
HttpSession session = request.getSession(false);//don't create if session doesn't exist.
if (session==null || session.getAttribute("username") == null) {
RequestDispatcher rd=request.getRequestDispatcher("login");//dispatch it to your desired page i.e login page
rd.forward(request, response);
} else {
chain.doFilter(req, res);
}
}
You should configure this filter inside web.xml or using Annotations for which url-patterns you want to filter.refer documentation for more details.
If you're using Tomcat then a good place to start is Tomcat Standard Realm Implementations.
It's important to remember that normal Java EE security authenticates users and authorises them using roles - even if you only have the one.
Once you have done that you can implement Logout by invoking a servlet which calls HttpServletRequest.logout() and then invalidates the HttpSession:
request.logout();
request.getSession().invalidate();
and then:
response.sendRedirect("some protected page");
which should resolve your back button problem and land back on the login page.
I have a problem with handling sessions between Java servlet, jsp page and Struts Action. Java servlet adds some param to session when get request and sendRedirect to some page1.jsp. On page1 I have an url to Struts Action like strutsAction.do. When StrutsAction recevies request, the session doesn't contain attributes I added in Java servlet. Clicking on page returned by this action doesnt refresh session of Java Servlet, but they have the same SessionId. So, after session.getMaxInactiveInterval() of servlet session pass I'm getting sessionDestroyed() event, even when i taking actions on page returned by StrutsAction. How to fix this issue?
In case of SendRedirect call old request and response object is lost because it’s treated as new request,
You should try the following code
RequestDispatcher rd = servletContext.getRequestDispatcher("/pathToResource");
rd.forward(request, response);
becuase when forward is called on requestdispather object we pass request and response object so our old request object is present on new resource which is going to process our request.
I'm trying to share a session between a liferay portlet and a servlet, running in the same WAR.
I'm setting the attribute like this in the LoginPostAction (Hook):
#Override
public void run(HttpServletRequest request, HttpServletResponse response) throws ActionException {
Gebruiker g = new Gebruiker();
request.getSession().setAttribute("gebruiker", gebruiker);
}
Trying to get this Gebruiker object in my servlet, through an AJAX-request:
#RequestMapping(value="/haalContactGegevens", method = RequestMethod.POST)
public #ResponseBody ContactGegevensMessage getContactGegevens(HttpServletRequest request, HttpServletResponse response) {
Gebruiker gebruiker = (Gebruiker)request.getSession(true).getAttribute("gebruiker");
}
But here my 'Gebruiker-object' stays null.
What am I doing wrong?
thx
Easy: The LoginPostAction is handled by Liferay (even though technically implemented in your webapp's context/classloader. However, if you look at the httpServletRequest's context path, it's Liferay's.
When you implement a servlet in your own webapp, it will have its own session, unrelated to Liferay's.
You should rather implement a portlet and utilize its serveResource lifecycle method to handle the Ajax request - this will make you part of the whole portal environment. However, you should also minimize use of the Http-level session: It's prone to become a source for memory leaks sooner or later.
Note: While implementing a portlet will give you access to the HttpServletRequest (through PortalUtil), this is discouraged for the reasons given above. But as I don't know what you're trying to achieve, this would be part of the quickfix for the code that you give in your question.
Somewhere in our chain of servlet filters there is a filter which forwards the request to the sign-in page when a 401 error is sent, as a usability tweak.
I'm trying to convert this to a Jetty handler because someone wants all web applications to be authenticated by the same logic instead of every webapp having to implement their own authentication.
(The main reason we're using a filter approach in the first place is that nobody was able to get Jetty's container-level authentication to work at all - we have the ability to choose Windows auth or built-in auth and want to be able to switch between these at runtime and were never able to figure out how to make that work with Jetty.)
Out in the Jetty handler, there is some logic like this:
private void handleErrorBetter(HttpServletRequest servletRequest,
HttpServletResponse servletResponse)
throws ServletException, IOException {
if (isPageRequest(servletRequest)) {
ServletContext rootContext = servletRequest.getServletContext().getContext("/");
RequestDispatcher dispatcher = rootContext.getRequestDispatcher("/sign_in");
dispatcher.forward(servletRequest, servletResponse);
} else {
// ...
}
}
servletRequest.getServletContext() appears to correctly return the context for /. Interestingly it appears to do this even if I make a request for a different webapp, but according to the Javadoc I have to use getContext("/") to be sure that I get the root context, so I'm doing that.
Getting the dispatcher succeeds too.
Then I call forward() and this always returns a 404 response to the client.
If I go to /sign_in directly from a web browser, the form loads.
There are only two contexts on the server: the root context /, and a /sample/ context which I'm using to test the second webapp. So I know that /sign_in will be in the root context, but why does forward() give a 404 when forwarding to it?
It turned out to be a bug.
https://bugs.eclipse.org/bugs/show_bug.cgi?id=386359
Short question: Is it possible to do a redirection, say when a user isn't logged in, when a page is rendered?
For that you should use a Filter.
E.g.
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
if (((HttpServletRequest) request).getSession().getAttribute("user") == null) {
((HttpServletResponse) response).sendRedirect("error.jsf"); // Not logged in, so redirect to error page.
} else {
chain.doFilter(request, response); // Logged in, so just continue.
}
}
Here I assume that the User is been placed in the session scope as you would normally expect. It can be a session scoped JSF managed bean with the name user.
A navigation rule is not applicable as there's no means of a "bean action" during a normal GET request. Also doing a redirect when the managed bean is about to be constructed ain't gong to work, because when a managed bean is to be constructed during a normal GET request, the response has already started to render and that's a point of no return (it would only produce IllegalStateException: response already committed). A PhaseListener is cumbersome and overwhelming as you actually don't need to listen on any of the JSF phases. You just want to listen on "plain" HTTP requests and the presence of a certain object in the session scope. For that a Filter is perfect.
Yes:
if(!isLoggedIn) {
FacesContext.getCurrentInstance().getExternalContext().redirect(url);
}
You can use a PhaseListener to specify when you want to do redirection.
In a PhaseListener try:
FacesContext ctx = FacesContext.getCurrentContext();
ctx.getApplication().getNavigationHandler()
.handleNavigation(ctx, null, "yourOutcome");