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.
Related
On my web application, which is hosted on Google App Engine, whenever I call a Servlet by typing in the URL on a browser, this results in two calls being made to the Servlet. However, if I make a call to the Servlet by clicking on an anchor, then only one call is made.
What is the cause and how can I correct this behavior?
Web.xml
<servlet>
<servlet-name>ServletOne</servlet-name>
<servlet-class>com.test.nz.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletOne</servlet-name>
<url-pattern>/myservlet</url-pattern>
</servlet-mapping>
Servlet:
public class MyServlet extends HttpServlet {
#Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException
{
final Logger log = Logger.getLogger(MyServlet.class.getName());
log.info("Here in MyServlet");
}
}
Update:
The issue appears to be caused by Google Chrome making requests on its own. Whenever I type in a URL, a request is made before I actually press enter, followed by the actual request. Is there any way to disallow these type of requests to my application?
I had the same issue, only in Chrome, turns out the servlet was mapped to / and was accepting requests for favicon.ico as well. For me this is the source of the second request.
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
Does RequestDispatcher work over multiple webapps ?
I'm asking because I had a single webapp working fine that uses RequestDispatcher rather than redirects so state isnt lost when displaying error and feedback messages.
However I now need to split some functionality between two webapps, so initial call is made from a webpage hosted on webapp1, calls webapp2 which eventually returns user to a page hosted on webapp1.
Clearly if webapps and webapp2 were on different websites using RequestDispatcher would not be possible but is it if both webapps are deployed within the same instance of a servlet container (tomcat 7)
Update
Got the request dispatcher part to work as explained in answer but am unable to retrieve data put in my webapp2 which iss why Im using it
i.e
webapp2 called , does some processing and then dispatches to a jsp on webapp1
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
HttpSession userSession = request.getSession(true);
String emailAddress = ......
String nextPage = /finish.jsp
userSession.setAttribute("DATA", emailAddress);
ServletContext otherContext = getServletContext().getContext("/webapp1");
otherContext.getRequestDispatcher(nextPage).forward(request, response);
}
webapp2 jsp file contains
...
<p>Email(<%=((String)session.getAttribute("DATA"))%>)</p>
...
but always displays null
Update 2 **
Im wondering if Im misunderstanding what crossContext="true" actually does . Does it make the same HttpSession availble in different webapps, or does it just make the ServletContext from one webap availble to another and hence allow one webapp to see the HttpSessions of another webapp ?
Im starting to think what Im doing is a bad idea as Ive always been keen to use vanilla servlet setups and never want to tie myself to a particular implementation. I think it might help if I explain why I flet the need to split the webapps in the first place.
I had a one webapp (webapp1), that was a website about a product I develop and code for purchasing that product using Google Checkout (now Google Wallet).
I then added created a new webapp for a new product (webapp2).
I then tried to add Google Checkout for new product into webapp2, but realised I couldnt do this easily because Google Checkout requires me to provide it with a url which it can call by application once it has processed payment so that I can then send
user a license. The url was already set to a servlet in webapp1, but
it wouldn't make sense for webapp1 to process payment s for product 2.
One option was to merge webpp1 and webapp2 into one webapp, but this goes against my general view of keeping things modular, it
would also mean evey time I would want to make chnages for one
product Id have to redeploy everything. It also meant big
modifications to webapp1 which I really didnt want to modify as it
was working and stable.
The alternative was to create webapp3 and then google url can point to this, and use this for processing purchases of product 1
and product 2 which is what Ive done. But the problem is when
purchasing product 1 the starting page is in webapp1 , and once
purchase has taken place I want to go back to a page in webapp1, but
only webapp3 has the details of the user who has just made the
purchase which I wanted to display on on the page in webapp1.
This is due to security reasons by default not possible. You need to configure Tomcat first to enable exposing the ServletContext of the current webapp to other webapps. This is to be done by setting the crossContext attribute of context.xml to true.
<Context ... crossContext="true">
Once done that, then you can use ServletContext#getContext() to obtain the other servlet context by its context path and finally use the RequestDispatcher as obtained by ServletContext#getRequestDispatcher() the usual way.
E.g.
ServletContext otherContext = getServletContext().getContext("/otherContext");
otherContext.getRequestDispatcher("/WEB-INF/some.jsp").forward(request, response);
Yes.
The first thing you need to do is get hold of a ServletContext for the other webapp. You do that with ServletContext::getContext on your own ServletContext, passing the context path of the other webapp.
Then, you simply do ServletContext::getRequestDispatcher as normal on the foreign context.
I haven't actually tried this, but i 100% guarantee that it will work.
I am not sure about different servlet container. But it works for same container by using
getServletContext().getContext() method.
First you need to make changes in below file
(Windows) C:\Program Files\Apache Software Foundation\Tomcat 7.0\conf\context.xml
Set value of crossContext to true.
context.xml
<Context crossContext="true">
<!-- Default set of monitored resources -->
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<!-- Uncomment this to disable session persistence across Tomcat restarts -->
<!--
<Manager pathname="" />
-->
<!-- Uncomment this to enable Comet connection tacking (provides events
on session expiration as well as webapp lifecycle) -->
<!--
<Valve className="org.apache.catalina.valves.CometConnectionManagerValve" />
-->
</Context>
Please note that crossContext="true".
Suppose you have two web applications with name InterServletComm1 and InterServletComm2
having servlets Servlet1 and Servlet1 in each web application respectively. Then the code in each servlets goes as follows:
Servlet1.java
package interServletComm1;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class Servlet1
*/
#WebServlet("/Servlet1")
public class Servlet1 extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* #see HttpServlet#HttpServlet()
*/
public Servlet1() {
super();
// TODO Auto-generated constructor stub
}
/**
* #see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
response.setContentType("text/html");
PrintWriter pw = response.getWriter();
request.setAttribute("name", "WebApp1");
ServletContext context = getServletContext().getContext("/InterServletComm2");
RequestDispatcher rd = context.getRequestDispatcher("/Servlet2");
rd.forward(request, response);
}
/**
* #see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
}
}
Servlet2.java
package interServletComm2;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class Servlet2
*/
#WebServlet("/Servlet2")
public class Servlet2 extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* #see HttpServlet#HttpServlet()
*/
public Servlet2() {
super();
// TODO Auto-generated constructor stub
}
/**
* #see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
response.setContentType("text/html");
PrintWriter pw = response.getWriter();
String name = (String) request.getAttribute("name");
pw.println("This is web application 2.");
pw.println("<br>The value received from web application one is: " + name);
}
/**
* #see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
}
}
Above code sends attribute name from InterServletComm1 and it is received in InterServletComm2.
Please let me know if this answer is not clear.
I'm currently trying to run a servlet that check a GET value and write the value.
Here my class :
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Servlet extends HttpServlet {
/**
*
*/
public Servlet() {
// TODO Auto-generated constructor stub
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
final String myValue = request.getParameter("MyValue");
if (myValue != null && !myValue.isEmpty()) {
response.getWriter().write(myValue);
}
}
}
It's quit simple, right ?
I already tried many url to be able to see my result like the following :
- http://localhost:8080/Servlet/servlet/Servlet
- http://localhost:8080/Servlet/servlet/Servlet?MyValue=Test
- http://127.0.0.1:8080/Servlet/servlet/Servlet
- http://127.0.0.1:8080/Servlet/servlet/Servlet?MyValue=Test
Is there something wrong with my code or is it a problem with my eclipse?
Thx
You didn't tell anything about the problem symptoms, but I'll assume that you're getting a HTTP 404 error page on all the attempts, right?
You need to map the servlet on an URL pattern. First, you need to assure that the servlet class is placed in a package (we'll assume com.example in this answer).
If you're still on Java EE 5 (or even J2EE..), register it in the webapp's /WEB-INF/web.xml (Eclipse should have autogenerated one):
<servlet>
<servlet-name>servlet</servlet-name>
<servlet-class>com.example.Servlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>servlet</servlet-name>
<url-pattern>/servlet</url-pattern>
</servlet-mapping>
(the servlet name is basically the instance variable name, there's only one applicationwide; the servlet class is obviously the FQN; the URL pattern the webcontent-relative URL of the servlet)
Or when you're already on the latest Java EE 6, then annotate it with #WebServlet wherein you specify the URL pattern as value:
package com.example;
// ...
#WebServlet("/servlet")
public class Servlet extends HttpServlet {
// ...
}
Either way, it's basically telling that the servlet should listen on webcontent-relative URLs matching /servlet. So, assuming that your web context root path is /Servlet, then this should do:
http://localhost:8080/Servlet/servlet
In the future, it'd be easier if you created the servlet class by New > Servlet instead of New > Class, then this all will be automagically taken into account in the wizard.
See also:
Our Servlets wiki page - contains some Hello World examples - you can get to this page by hovering your mouse a while above the servlets until a black info box shows up and then clicking the info link therein.
You can find your Context Root by right clicking your project in eclipse -> Properties -> Web Project Settings.
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.