【问题标题】:Displaying SimpleCaptcha in Struts 2 Form以 Struts 2 形式显示 SimpleCaptcha
【发布时间】:2015-01-13 07:07:17
【问题描述】:

我正在尝试使用 Struts 2 实现 SimpleCaptcha,目前图像正在显示。但是,它显示在<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>

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

【问题讨论】:

    标签: java jsp struts2 captcha simplecaptcha


    【解决方案1】:

    图像应由captcha 操作生成。然后在 &lt;img&gt; 标记中提供此操作的 URL。要在您的项目中实施验证码,请按照以下步骤操作

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

    2. 添加新的动作类RegisterAction

    注意:以下代码使用convention plugin 映射动作,为简单起见,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>
    

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

    注意:我们在这里使用的一个好技巧是 javascript Math.random() 函数,这样可以防止某些浏览器(如 Firefox)缓存 URL 并继续发布相同的验证码图像,这会强制它获取新值而无需再做任何事情努力。

    它的外观如下:

    更多详情请参考网站:SimpleCaptcha

    【讨论】:

    • 感谢您的回答超出了所要求的范围。它肯定会对每个人都有帮助。我还根据您在上面链接的 SimpleCaptcha 的 sourceforge J2EE 示例发布了一个答案。
    【解决方案2】:

    这只是为了展示我是如何解决这个问题的。我不知道您可以将&lt;tr&gt;&lt;td&gt; 放在&lt;s:form&gt; 中。感谢 Roman C,我得到了验证码图像,可以显示在我想要的位置。

    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"
                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>
    

    RegisterAction.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:
    &lt;init-param&gt; 是可选的。)

    <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>
    

    输出:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-15
      相关资源
      最近更新 更多