【问题标题】:Implementing reCaptcha with Apache Shiro使用 Apache Shiro 实现 reCaptcha
【发布时间】:2015-07-29 20:15:21
【问题描述】:

我有一个使用 Apache Shiro 保护的 web 应用程序,并且一切正常。现在我想将 Goolge 的 reCaptcha 添加到我的登录页面,但不知道该怎么做。

验证码本身已添加并且工作正常,我需要帮助的部分是现在如何将其与 Shiro 集成以在继续验证用户之前进行验证。

根据我从 docs 收集到的信息,这将通过过滤器链完成。

所以我把这个放到我的shiro.ini:

[main]
authc.failureKeyAttribute = shiroLoginFailure
authc.loginUrl = /login.jsp
authc.successUrl = /LogIn
logout.redirectUrl = /login.jsp
captcha = path.to.my.class.VerifyUserFilter

...

[urls]
/login.jsp = captcha,authc
/* = authc

我知道如何实现验证验证码的逻辑。我不知道的是,除了实际的验证逻辑之外,VerifyUserFilter 类需要看起来像什么才能使其工作。基本上它需要做的就是发布到 Google API、获取响应、解析它并根据结果将请求传递给下一个过滤器或在验证失败时停止。

在发布此内容之前,我决定最后一次尝试,并花了几个小时尝试不同的东西,最终让它发挥作用!无论如何,我仍然决定发布这个问题,以及我自己的答案,因为我在研究这个问题时找不到太多帮助,也想看看我所做的是否正确。如果有更好或更合适的方法可以做到这一点,我想知道。

【问题讨论】:

    标签: java web-applications recaptcha shiro


    【解决方案1】:

    这是我解决这个问题的方法。

    首先我将我的shiro.ini 设置如下(相关部分):

    [main]
    authc.failureKeyAttribute = shiroLoginFailure
    authc.loginUrl = /login.jsp
    authc.successUrl = /LogIn
    logout.redirectUrl = /login.jsp
    captcha = path.to.my.class.VerifyUserFilter
    
    ...
    
    [urls]
    /login.jsp = captcha,authc
    /* = authc 
    

    然后我通过扩展FormAuthenticationFilter 类并覆盖读取参数的doFilterInternal 方法创建了我的VerifyUserFilter 类,调用Google API 以验证响应,然后根据结果重定向如果验证失败或移动到过滤器链中的下一项 - 在这种情况下为authc,则转到登录页面。

    这是我的VerifyUserFilter 类的完整实现:​​

    import org.apache.shiro.web.util.WebUtils;
    
    public class VerifyUserFilter extends org.apache.shiro.web.filter.authc.FormAuthenticationFilter {
    
        @Override
        public void doFilterInternal(ServletRequest request, ServletResponse response, FilterChain chain)
                throws ServletException, IOException {
            org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(VerifyUserFilter.class);
            if (isLoginSubmission(request, response)){   
                String user =  WebUtils.getCleanParam(request, "username");
                String verifId = WebUtils.getCleanParam(request, "g-recaptcha-response");
                log.debug("Verif ID: " + verifId);
                if (verifId == null || "".equals(verifId)) {                
                    log.warn("User " + user + " missed the captcha challenge and is returned to login page.");
                    saveRequestAndRedirectToLogin(request, response);                
                } else {
                    // Now do the verification of the captcha
                    final String url = "https://www.google.com/recaptcha/api/siteverify";
                    final String secret = "6Lxxxxxxxxxxxxxx";
                    // Send the POST request to the Google API
                    URL obj = new URL(url);
                    HttpsURLConnection con = (HttpsURLConnection)obj.openConnection();
                    con.setRequestMethod("POST");
                    String params = "secret=" + secret + "&response=" + verifId;
                    con.setDoOutput(true);
                    DataOutputStream wr = new DataOutputStream(con.getOutputStream());
                    log.debug("Sending POST to " + url);
                    wr.writeBytes(params);
                    wr.flush();
                    wr.close();
                    // Get the response code
                    int respCode = con.getResponseCode();
                    log.debug("Response code: " + respCode);
                    // Read in the response data
                    BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
                    String line;
                    StringBuilder input = new StringBuilder();
                    log.debug("Reading response data...");
                    while ((line = in.readLine()) != null){
                        input.append(line);
                    }
                    in.close();
                    log.debug("Reponse data: " + input);
                    // Parse the json received to determine if the verif was successful
                    JsonReader jr = Json.createReader(new StringReader(input.toString()));
                    JsonObject jo = jr.readObject();
                    jr.close();                
                    if (jo.getBoolean("success")){                  
                        log.debug("User " + user + " is good to go, not a robot!");
                        // Move on to the next filter
                        chain.doFilter(request, response);
                    } else {
                        // User did not solve the captcha, return to login page
                        log.warn("User " + user + " failed the captcha challenge and is returned to login page.");
                        saveRequestAndRedirectToLogin(request, response);                    
                    }
                }                  
            } else {
                log.debug("Not a login attempt, carry on.");
                chain.doFilter(request, response);
            }
        }              
    }
    

    【讨论】:

      猜你喜欢
      • 2013-06-11
      • 2016-11-21
      • 2020-02-06
      • 2021-06-07
      • 1970-01-01
      • 2012-04-13
      • 2015-03-05
      • 2014-06-08
      • 2021-07-30
      相关资源
      最近更新 更多