使用Apache Shiro实现reCaptcha

时间:2015-05-18 10:52:16

标签: java web-applications recaptcha shiro

我有一个使用Apache Shiro保护的webapp,一切正常。现在我想将Goolge的reCaptcha添加到我的登录页面,并且无法弄清楚如何做到这一点。

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

根据我从docs收集的内容,我们可以使用过滤器链。

所以我把它放到[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

shiro.ini

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

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

1 个答案:

答案 0 :(得分:0)

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

首先,我将[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

然后我通过扩展FormAuthenticationFilter类并覆盖读取参数的doFilterInternal方法创建了我的authc类,调用Google API来验证响应然后根据结果重定向到登录页面,如果verif失败或移动到过滤器链中的下一个项目 - 在这种情况下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); } } } 课程的完整实施:

Random random = new Random(System.currentTimeMillis());

public void test() {
    for (int i = 0; i < 10; i++) {
        String n = BigInteger.valueOf(Math.abs(random.nextLong())).toString(32).toUpperCase();
        if (n.length() > 8) {
            if (n.length() > 10) {
                n = n.substring(n.length() - 10);
            }
            System.out.println(n);
        }
    }
}
相关问题