【问题标题】:Captcha in spring mvc/security applicationSpring MVC/安全应用程序中的验证码
【发布时间】:2016-06-15 19:58:21
【问题描述】:

我需要为 spring 应用程序实现一个验证码。

我正在研究不同的选项,虽然很多人推荐 reCaptcha,但很可能我们不能使用它,因为应用程序是内部的(无法访问互联网)。

让我信服的选项是 BotDetect(因为 SimpleCaptcha 没有具体说明对 Java 1.7 的支持)

我们将身份验证留给 Spring Security,因此我们没有带有 @RequestMapping("/login") 的控制器,我决定通过拦截器验证验证码,覆盖 preHandle 方法。

我的问题是我无法从拦截器中检索验证码,由于某种原因未包含在请求中。

我的代码基于文档 BotDetect (https://captcha.com/doc/java/howto/springmvc-captcha.html)

知道为什么不工作吗?或者如果有任何其他替代方法可以使用 Spring Security 实现验证码,欢迎使用

这是我的jsp:

<form action="/businessPortal/login" method="post" role="form">
    <div class="form-group">
        <label for="userName">
            <spring:message code="IntroPage.UserName" />:
        </label>
        <input type="text"  id="userName" name="j_username" class="form-control" tabindex="1">
    </div>
    <p class="divider"></p>
    <div class="form-group">
        <label for="password">
            <spring:message code="IntroPage.Password" />:
        </label>
            <input type="password" id="password" name="j_password" class="form-control" tabindex="2">
    </div>
    <p class="divider"></p>
    <div class="form-group">
        <botDetect:captcha id="basicExampleCaptcha"/>
        <div class="validationDiv">
            <input id="captchaCodeTextBox" type="text" name="captchaCodeTextBox" value="${basicExample.captchaCodeTextBox}"/>
        </div>
    </div>
    <input type="submit" class="btn btn-primary btn-lg" value="Iniciar Sesión" />
</form>

这是我的 spring 安全配置:

<sec:http use-expressions="true" auto-config="false">
    ...
    <sec:form-login login-page="/login"
        authentication-failure-url="/accessDenied"
        authentication-success-handler-ref="authSuccessHandler"
        authentication-failure-handler-ref="authFailureHandler"
        login-processing-url="/login" />
    <sec:access-denied-handler error-page="/accessDenied" />
    <sec:logout />
</sec:http>

拦截器配置:

<mvc:interceptors>
    <bean id="validateCaptchaInterceptor"  class="com.project.backend.security.captcha.ValidateCaptchaInterceptor">
    </bean>
</mvc:interceptors>

这是拦截器代码:

public class ValidateCaptchaInterceptor extends HandlerInterceptorAdapter{

    private static final Logger logger = Logger.getLogger(ValidateCaptchaInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object command){
        boolean isHuman = true;
        if(request.getRequestURL().toString().indexOf("login") != -1){
            BasicExample basicExample = (BasicExample)command;
            // validate the Captcha to check we're not dealing with a bot
            Captcha captcha = Captcha.load(request, "basicExampleCaptcha");
            isHuman = captcha.validate(request,basicExample.getCaptchaCodeTextBox());
        }
        return isHuman;
    }
}

【问题讨论】:

  • 为什么在无法通过互联网访问的网站上需要验证码?
  • 根据我的客户所说,他们很关心自己的员工。我同意这没有任何意义,但我们无法说服他们否则:S.

标签: java spring spring-mvc spring-security captcha


【解决方案1】:

解决了

我终于用过滤器(不是拦截器)解决了

这是我的过滤器和声明(我想在 FORM_LOGIN_FILTER 之前执行这个过滤器)

<sec:http use-expressions="true" auto-config="false">
    ...
    <sec:custom-filter ref="captchaFilter" before="FORM_LOGIN_FILTER"/>
    ...
</sec:http>

<bean id="captchaFilter" class="path.to.my.filter.CaptchaFilter" p:postOnly="false">
    <property name="authenticationManager" ref="authenticationManager" />
    <property name="authenticationFailureHandler" ref="authFailureHandler" />
    <property name="authenticationSuccessHandler" ref="authSuccessHandler" />
    <property name="restTemplate" ref="commonRestTemplate" />
</bean>

这是我的过滤代码:

public class CaptchaFilter extends UsernamePasswordAuthenticationFilter {

@Autowired
private RestTemplate restTemplate;
private static final String POST = "POST";
private static final Logger LOG = Logger.getLogger(UsernamePasswordAuthenticationFilter.class);

@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
  ...
} 

  @Override
  public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
    final HttpServletRequest request = (HttpServletRequest) req;
    final HttpServletResponse response = (HttpServletResponse) res;
    if(request.getRequestURI().indexOf("login") != -1 && request.getMethod().equals(POST) && 
       LoginAttemptsSingleton.getInstance().getLoginAttepmts().containsKey(ipAddress) &&
       LoginAttemptsSingleton.getInstance().getLoginAttepmts().get(ipAddress) > 3){
        //Captcha validation here
    }else{
        //No captcha validation, so keep going throug next filter in chain
        chain.doFilter(request, response);
    }
  }
 }

【讨论】:

  • 嗨,我有一个问题,验证码验证后会发生什么,它如何重定向到登录页面?谢谢。
猜你喜欢
  • 2013-03-05
  • 1970-01-01
  • 1970-01-01
  • 2012-03-12
  • 2014-04-11
  • 2019-07-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多