1

我正在尝试SimpleCaptcha使用 Struts 2 来实现,到目前为止图像正在显示。但是,它显示在<s:form>.

在此处输入图像描述

注册.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>

如何使图像显示Enter CAPTCHA在代码中指定的文本字段上方?

4

2 回答 2

1

图像应该由captcha动作生成。<img>然后在标签中提供此操作的 URL 。要在您的项目中实施验证码,请按照以下步骤操作

  1. 将 jar 添加到您的 Web 项目类路径:simplecaptcha-1.2.1.jar. 通常在web-inf/lib文件夹内。

  2. 添加新的动作类RegisterAction

注意:以下代码使用约定插件来映射动作,为简单起见,DMI 用于在提交表单时调用动作类的某些方法。要打开 DMI,请使用以下常量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包含错误键的以下值:

RegisterAction.properties

error.captcha=Invalid value of shown text!

所以我们检查是否成功通过或添加关于验证码的错误错误。

  1. register.jsp通常添加在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>

这将构造验证码和文本字段以输入值和 Struts 错误消息以显示captchaResponse字段中的错误,以及刷新图标。

注意:我们在这里使用的一个好技巧是 javascriptMath.random()函数,这样可以防止某些浏览器(如 Firefox)缓存 URL 并继续发布相同的 Captcha 图像,这会强制它获取新值而无需付出更多努力。

这是它的样子: 在此处输入图像描述

有关详细信息,请参阅网站:SimpleCaptcha

于 2014-11-16T12:57:00.137 回答
0

这只是为了展示我是如何解决这个问题的。我不知道你可以<tr><td><s:form>. 感谢Roman C,我得到了验证码图像来显示我想要的位置。

注册.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"
            placeholder="someone" size="30" />
        <s:textfield label="Enter email" key="userEmail1"
            placeholder="someone@domain.com" size="30" />
        <s:textfield label="Confirm email" key="userEmail2"
            placeholder="someone@domain.com" size="30" />
        <s:password label="Enter password" key="userPassword1" size="30" />
        <s:password label="Confirm password" key="userPassword2"
            size="30" />
        <tr>
            <td></td>
            <td>
                <img src="<c:url value='simple-captcha.png' />" />
                <br />
                Cannot read? Press F5 to refresh.
            </td>
        </tr>
        <s:textfield label="Enter code" key="captchaAnswer" size="30" />
        <s:submit value="Register" />
    </s:form>
</body>

注册动作.java:

import nl.captcha.Captcha;
...

public class RegisterAction extends ActionSupport implements SessionAware, Message {
    private static final long serialVersionUID = 1L;

    private Map<String, Object> session;

    private String userId;
    private String userEmail1;
    private String userEmail2;
    private String userPassword1;
    private String userPassword2;
    private String captchaAnswer;

    @Override
    public String execute() throws Exception {      
        // business logic to insert user into database

        return SUCCESS;
    }

    @Override
    public void validate() {
        Captcha captcha = (Captcha) session.get(Captcha.NAME);

        if(!captcha.isCorrect(getCaptchaAnswer())) {
            addFieldError("captchaAnswer", INCORRECT_CAPTCHA);
        }

        // other validations
    }

    @Override
    public void setSession(Map<String, Object> session) {
        this.session = session;
    }

    // getters and setters
}

struts.xml:

<struts>
    <constant name="struts.devMode" value="true" />
    <package name="default" extends="struts-default">
        <action name="register" class="com.mypackage.action.RegisterAction">
            <result name="success">/login.jsp</result>
            <result name="input">/register.jsp</result>
        </action>

        <!-- other actions -->
    </package>
</struts>

web.xml:(
<init-param>是可选的。)

<servlet>
    <servlet-name>SimpleCaptcha</servlet-name>
    <servlet-class>nl.captcha.servlet.SimpleCaptchaServlet</servlet-class>
    <init-param>
        <param-name>captcha-width</param-name>
        <param-value>200</param-value>
    </init-param>
    <init-param>
        <param-name>captcha-height</param-name>
        <param-value>50</param-value>
    </init-param>
</servlet>

<servlet-mapping>
    <servlet-name>SimpleCaptcha</servlet-name>
    <url-pattern>/simple-captcha.png</url-pattern>
</servlet-mapping>

<filter>
    <filter-name>struts2</filter-name>
    <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>struts2</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

输出:

在此处输入图像描述

于 2014-11-17T06:46:45.207 回答