You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by ug...@apache.org on 2005/05/18 16:43:06 UTC
svn commit: r170759 - in /cocoon/branches/BRANCH_2_1_X/src/blocks/forms:
java/org/apache/cocoon/forms/formmodel/CaptchaField.java
java/org/apache/cocoon/forms/validation/impl/CaptchaValidator.java
java/org/apache/cocoon/forms/validation/impl/CaptchaValidatorBuilder.java
samples/resources/forms-field-styling.xsl
Author: ugo
Date: Wed May 18 07:43:05 2005
New Revision: 170759
URL: http://svn.apache.org/viewcvs?rev=170759&view=rev
Log:
Use random string for session attribute name instead of field id, as suggested by Vadim
Modified:
cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/formmodel/CaptchaField.java
cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/validation/impl/CaptchaValidator.java
cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/validation/impl/CaptchaValidatorBuilder.java
cocoon/branches/BRANCH_2_1_X/src/blocks/forms/samples/resources/forms-field-styling.xsl
Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/formmodel/CaptchaField.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/formmodel/CaptchaField.java?rev=170759&r1=170758&r2=170759&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/formmodel/CaptchaField.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/formmodel/CaptchaField.java Wed May 18 07:43:05 2005
@@ -15,22 +15,25 @@
*/
package org.apache.cocoon.forms.formmodel;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
import java.util.Locale;
import java.util.Map;
+import org.apache.avalon.framework.CascadingRuntimeException;
import org.apache.avalon.framework.context.Context;
import org.apache.cocoon.components.ContextHelper;
import org.apache.cocoon.environment.ObjectModelHelper;
import org.apache.cocoon.environment.Session;
import org.apache.cocoon.forms.Constants;
-import org.apache.cocoon.xml.XMLUtils;
+import org.apache.cocoon.xml.AttributesImpl;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
/**
* A {@link Field} for CAPTCHA validation. Upon generation, a secret random string is stored
- * in a session attribute having the same name as the field's ID, for use by a
+ * in a session attribute having a randomly generated name, for use by a
* {@link org.apache.cocoon.forms.validation.impl.CaptchaValidator}.
* <br>
* Usage sample:
@@ -49,33 +52,68 @@
*/
public class CaptchaField extends Field {
- private static final String IMAGE_EL = "captcha-image";
public static final String SESSION_ATTR_PREFIX = "captcha-";
+
+ private static final String IMAGE_EL = "captcha-image";
private static final String SECRET_CHARS = "abcdefghijkmnopqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ123456789";
private static final int SECRET_LENGTH = 7;
+ private static final int SESSION_ATTR_NAME_LENGTH = 6;
+
private Context avalonContext;
+
+ /**
+ * Random number generator used to create session attribute name.
+ */
+ protected static SecureRandom random;
+
+ static {
+ try {
+ random = SecureRandom.getInstance("SHA1PRNG");
+ } catch(java.security.NoSuchAlgorithmException nsae) {
+ // Maybe we are on IBM's SDK
+ try {
+ random = SecureRandom.getInstance("IBMSecureRandom");
+ } catch (NoSuchAlgorithmException e) {
+ throw new CascadingRuntimeException("No random number generator available", e);
+ }
+ }
+ random.setSeed(System.currentTimeMillis());
+ }
+
+ public CaptchaField(FieldDefinition fieldDefinition, Context avalonContext) {
+ super(fieldDefinition);
+ this.avalonContext = avalonContext;
+ }
private String generateSecret() {
StringBuffer secret = new StringBuffer(SECRET_LENGTH);
for (int n = 0 ; n < SECRET_LENGTH ; n++) {
- int randomnumber = (int) Math.floor(SECRET_CHARS.length() * Math.random());
+ int randomnumber = random.nextInt(SECRET_CHARS.length());
secret.append(SECRET_CHARS.charAt(randomnumber));
}
return secret.toString();
}
- public CaptchaField(FieldDefinition fieldDefinition, Context avalonContext) {
- super(fieldDefinition);
- this.avalonContext = avalonContext;
- }
-
public void generateItemSaxFragment(ContentHandler contentHandler, Locale locale) throws SAXException {
super.generateItemSaxFragment(contentHandler, locale);
- contentHandler.startElement(Constants.INSTANCE_NS, IMAGE_EL, Constants.INSTANCE_PREFIX_COLON + IMAGE_EL, XMLUtils.EMPTY_ATTRIBUTES);
- contentHandler.endElement(Constants.INSTANCE_NS, IMAGE_EL, Constants.INSTANCE_PREFIX_COLON + IMAGE_EL);
+ byte[] bytes = new byte[SESSION_ATTR_NAME_LENGTH];
+ char[] result = new char[bytes.length * 2];
+ random.nextBytes(bytes);
+ for (int i = 0; i < SESSION_ATTR_NAME_LENGTH; i++) {
+ byte ch = bytes[i];
+ result[2 * i] = Character.forDigit(Math.abs(ch >> 4), 16);
+ result[2 * i + 1] = Character.forDigit(Math.abs(ch & 0x0f), 16);
+ }
+ String id = new String(result);
Map objectModel = ContextHelper.getObjectModel(this.avalonContext);
Session session = ObjectModelHelper.getRequest(objectModel).getSession(true);
- session.setAttribute(SESSION_ATTR_PREFIX + getId(), generateSecret());
+ String secret = generateSecret();
+ session.setAttribute(SESSION_ATTR_PREFIX + id, secret);
+ this.setAttribute("secret", secret);
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "id", "id", "PCDATA", id);
+ contentHandler.startElement(Constants.INSTANCE_NS, IMAGE_EL, Constants.INSTANCE_PREFIX_COLON + IMAGE_EL, attrs);
+ contentHandler.endElement(Constants.INSTANCE_NS, IMAGE_EL, Constants.INSTANCE_PREFIX_COLON + IMAGE_EL);
}
}
Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/validation/impl/CaptchaValidator.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/validation/impl/CaptchaValidator.java?rev=170759&r1=170758&r2=170759&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/validation/impl/CaptchaValidator.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/validation/impl/CaptchaValidator.java Wed May 18 07:43:05 2005
@@ -15,13 +15,6 @@
*/
package org.apache.cocoon.forms.validation.impl;
-import java.util.Map;
-
-import org.apache.avalon.framework.context.Context;
-import org.apache.cocoon.components.ContextHelper;
-import org.apache.cocoon.environment.ObjectModelHelper;
-import org.apache.cocoon.environment.Session;
-import org.apache.cocoon.forms.formmodel.CaptchaField;
import org.apache.cocoon.forms.formmodel.Widget;
import org.apache.cocoon.forms.validation.ValidationError;
import org.apache.cocoon.forms.validation.ValidationErrorAware;
@@ -37,27 +30,14 @@
*/
public class CaptchaValidator implements WidgetValidator {
- private final Context avalonContext;
private static final String VALIDATION_MESSAGE_KEY = "validation.captcha.mismatch";
-
- public CaptchaValidator(Context avalonContext) {
- this.avalonContext = avalonContext;
- }
public boolean validate(Widget widget) {
if (! (widget instanceof ValidationErrorAware)) {
// Invalid widget type
throw new IllegalArgumentException("Widget '" + widget.getRequestParameterName() + "' is not ValidationErrorAware");
}
- Map objectModel = ContextHelper.getObjectModel(this.avalonContext);
- Session session = ObjectModelHelper.getRequest(objectModel).getSession(false);
- if (session == null) {
- throw new RuntimeException("No session associated with request.");
- }
- if (session.getAttribute(CaptchaField.SESSION_ATTR_PREFIX + widget.getId()) == null) {
- throw new RuntimeException("No CAPTCHA attribute associated with widget " + widget.getId());
- }
- boolean result = widget.getValue() != null && widget.getValue().equals(session.getAttribute(CaptchaField.SESSION_ATTR_PREFIX + widget.getId()));
+ boolean result = widget.getValue() != null && widget.getValue().equals(widget.getAttribute("secret"));
if (! result) {
((ValidationErrorAware) widget).setValidationError(new ValidationError(VALIDATION_MESSAGE_KEY));
}
Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/validation/impl/CaptchaValidatorBuilder.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/validation/impl/CaptchaValidatorBuilder.java?rev=170759&r1=170758&r2=170759&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/validation/impl/CaptchaValidatorBuilder.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/validation/impl/CaptchaValidatorBuilder.java Wed May 18 07:43:05 2005
@@ -15,9 +15,6 @@
*/
package org.apache.cocoon.forms.validation.impl;
-import org.apache.avalon.framework.context.Context;
-import org.apache.avalon.framework.context.ContextException;
-import org.apache.avalon.framework.context.Contextualizable;
import org.apache.avalon.framework.thread.ThreadSafe;
import org.apache.cocoon.forms.formmodel.WidgetDefinition;
import org.apache.cocoon.forms.validation.WidgetValidator;
@@ -31,18 +28,11 @@
* @see org.apache.cocoon.forms.validation.impl.CaptchaValidator
* @version $Id$
*/
-public class CaptchaValidatorBuilder implements WidgetValidatorBuilder, Contextualizable, ThreadSafe {
-
- private Context avalonContext;
-
- public void contextualize(Context context) throws ContextException {
- System.err.println("CaptchaValidatorBuilder.contextualize(" + context + ")");
- this.avalonContext = context;
- }
+public class CaptchaValidatorBuilder implements WidgetValidatorBuilder, ThreadSafe {
public WidgetValidator build(Element validationRuleElement,
WidgetDefinition definition) throws Exception {
- return new CaptchaValidator(avalonContext);
+ return new CaptchaValidator();
}
}
Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/forms/samples/resources/forms-field-styling.xsl
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/forms/samples/resources/forms-field-styling.xsl?rev=170759&r1=170758&r2=170759&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/forms/samples/resources/forms-field-styling.xsl (original)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/forms/samples/resources/forms-field-styling.xsl Wed May 18 07:43:05 2005
@@ -49,7 +49,7 @@
+-->
<xsl:template match="fi:field">
<xsl:if test="fi:captcha-image">
- <img src="captcha-{@id}.jpg" style="vertical-align:middle"/>
+ <img src="captcha-{fi:captcha-image/@id}.jpg" style="vertical-align:middle"/>
<xsl:text> </xsl:text>
</xsl:if>
<input name="{@id}" id="{@id}" value="{fi:value}" title="{fi:hint}" type="text">