I am trying to implement SimpleCaptcha
with Struts 2, so far the image is displaying. However, it is displaying at the top of the <s:form>
.
register.jsp:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<head>
...
<s:head />
</head>
<body>
<b>REGISTER</b>
<p>Please fill up the form below.</p>
<s:form action="register" method="post">
<s:textfield label="Enter username" key="userId" maxlength="25"
size="30" />
<s:textfield label="Enter email" key="userEmail1" type="email"
placeholder="someone@domain.com" size="30" />
<s:textfield label="Re-enter email" key="userEmail2" type="email"
placeholder="someone@domain.com" size="30" />
<s:password label="Enter password" key="userPassword1" size="30" />
<s:password label="Re-enter password" key="userPassword2"
size="30" />
<img src="<c:url value='simple-captcha.png' />" />
<br />
Cannot read? Refresh page for new CAPTCHA.
<s:textfield label="Enter CAPTCHA" key="captchaAnswer" size="30" />
<s:submit value="Register" />
</s:form>
</body>
How do I make the image appear above the Enter CAPTCHA
textfield as specified in the code?
The image should be generated by the captcha
action. Then you provide the URL to this action in <img>
tag. To implement captcha in your project follow steps below
Add the jar to your web project classpath: simplecaptcha-1.2.1.jar
.
Typically inside web-inf/lib
folder.
Add new action class RegisterAction
Note: The following code is using convention plugin to map actions and for simplicity DMI is used to invoke some methods of the action class when form is submitted. To turn on DMI use a constant in struts.xml
:
<constant name="struts.enable.DynamicMethodInvocation" value="true"/>
RegisterAction.java
:
public class RegisterAction extends ActionSupport {
private String userId;
private String userEmail1;
private String userEmail2;
private String userPassword1;
private String userPassword2;
private String captchaResponse;
private InputStream inputStream;
//getters and setters
public String create() {
//RegisterAction is the form bean of the current action and captchaResponse is the field of user input
String answer = (String) ActionContext.getContext().getSession().get("CorrectAnswer");
if (answer == null || getCaptchaResponse()==null || !answer.equals(getCaptchaResponse())){
addFieldError("captchaResponse", getText("error.captcha"));
}
return SUCCESS;
}
@Action(value = "captcha", results = {@Result(type="stream", params = {"contentType", "image/jpeg"})})
public String captcha() {
try {
Captcha captcha = new Captcha.Builder(200, 50).addText(new DefaultTextProducer()).gimp(new DropShadowGimpyRenderer()).build();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
//write the image
CaptchaServletUtil.writeImage(outputStream, captcha.getImage());
//store the answer for this in session
ActionContext.getContext().getSession().put("CorrectAnswer", captcha.getAnswer());
//return image
inputStream = new ByteArrayInputStream(outputStream.toByteArray());
return SUCCESS;
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
}
RegisterAction.properties
contains the following value for the error key:
RegisterAction.properties
:
error.captcha=Invalid value of shown text!
so we check either pass successfully or add to errors error regarding captcha.
register.jsp
Typically in web-inf\content
register.jsp
:
<!DOCTYPE html>
<%@ taglib prefix="s" uri="/struts-tags"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
<meta charset="UTF-8">
<title>Register</title>
</head>
<body>
<b>REGISTER</b>
<p>Please fill up the form below.</p>
<s:form action="register" method="post">
<s:textfield label="Enter username" key="userId" maxlength="25"
size="30" />
<s:textfield label="Enter email" key="userEmail1" type="email"
placeholder="someone@domain.com" size="30" />
<s:textfield label="Re-enter email" key="userEmail2" type="email"
placeholder="someone@domain.com" size="30" />
<s:password label="Enter password" key="userPassword1" size="30" />
<s:password label="Re-enter password" key="userPassword2"
size="30" />
<tr><td>
<img id="captchaImg" src="<s:url action='captcha'/>" alt="Captcha Image" height="45">
<img src="<c:url value='/images/reload.jpg' />" alt="Reload" onclick="document.forms[0].captchaImg.src='<s:url action='captcha'/>'+'?id='+Math.random();" style="cursor:pointer"/>
<s:textfield label="Enter CAPTCHA" key="captchaResponse" size="30" requiredLabel="*"/>
<tr><td>
Cannot read? Refresh page for new CAPTCHA.
</td></tr>
<s:submit method="create" value="Register" />
</s:form>
</body>
</html>
This will construct the Captcha and the text field to enter the value and Struts error message to show errors in captchaResponse
field, plus the refresh icon.
NOTE: a good trick we used here is the javascript Math.random()
function, this way prevent certain browsers like Firefox to cache the URL and keep posting the same Captcha image, this enforce it to get the new value without doing any more effort.
Here is how it will looks like:
For more details refer to the web site : SimpleCaptcha