为什么我们需要为google recaptcha进行服务器端验证?

时间:2017-05-04 11:54:02

标签: validation spring-boot spring-security recaptcha

在我的新项目中,我将包括google recaptcha。 我的问题相当简单,即使我们做客户端验证用户不是机器人,即使建议进行服务器端验证。 我想知道为什么有必要为google recaptcha进行服务器端验证?它是如何添加额外的安全层的?如何在弹簧安全的春季启动?

2 个答案:

答案 0 :(得分:2)

服务器端验证必须!! reCAPTCHA的设计方式是客户端只生成' g-captcha-response'与密钥(存储在服务器端)一起发送到https://www.google.com/recaptcha/api/siteverify进行验证。响应是一个JSON,它声明成功为真或假,并进一步推送到客户端。仅在客户端进行验证在技术上是可行的,但它失败了目的。此外,如果仅进行客户端验证,则可能会在控制台中收到CORS(跨源资源共享)策略错误。我可以分享步骤在servlet中进行简单的基于Java的服务器端验证。如果您需要,请告诉我。

答案 1 :(得分:1)

这是代码。几点需要注意:

  1. 参数userResponse = request.getParameter(“recaptchaResponse”)是我在用户点击UI上的reCAPTCHA小部件时获得用户生成的'g-recaptcha-response'的方式。在你的javascript上,捕获字段'g-recaptcha-response'的值并将其附加到请求中。然后在servlet中,我们可以从request.getParameter获取它。 示例代码:

     var recaptchaResponse = document.getElementById("g-recaptcha-response").value;
     //alert("g-recaptcha-response= "+recaptchaResponse);
     if (recaptchaResponse.length > 0)
     { 
       var xmlhttp1;
       if (window.XMLHttpRequest)
        {
          xmlhttp1=new XMLHttpRequest();
        }
       else
        {
          xmlhttp1=new ActiveXObject("Microsoft.XMLHTTP");
        }
        var query1 = "?recaptchaResponse=" + recaptchaResponse;
        xmlhttp1.open("POST","captchaVerificationServlet" + query1, false);
        xmlhttp1.send(null);   
        var resp1 = xmlhttp1.responseText;
        alert("resp1= "+resp1);
        if(resp1=='matched'){
            return true;
        }
        else{
            alert("resp1 did not match");
            return false;
        }
      } 
      else{
         alert("error: recaptcha response is blank");
         return false;
      }
    
    1. 为简单起见,我在返回的JSON响应中检查“success:true”的存在。如您所知,返回的JSON包含两个参数:成功和错误代码。您可以使用JSONReader读取和解析JSON并完全获取所有参数。示例代码将是  JsonReader rdr = Json.createReader(your_inputstream);  JsonObject jsonObject = rdr.readObject();
    2. 不用说,删除生产中的所有警报和索引语句!
  2. public class CaptchaVerificationServlet扩展HttpServlet {       private static final String sec = YOUR_SECRET_KEY;       public void processRequest(HttpServletRequest request,HttpServletResponse response)           抛出ServletException,IOException {}

      protected void doPost(HttpServletRequest request, HttpServletResponse response)
                  throws ServletException, IOException {     
            String userResponse = request.getParameter("recaptchaResponse");
            response.setCharacterEncoding("UTF-8"); 
            System.out.println("userResponse= "+userResponse);
            //verify user response with Google ReCaptcha API
            String ipAddress = request.getRemoteAddr(); //get client's ip address
            System.out.println("ipAddress= "+ipAddress);
            try{
                String s = validateCaptcha(sec, userResponse, ipAddress);
                Boolean success = (s.contains("\"success\": true"));
                if(success)
                  response.getWriter().write("matched");
            }
            catch(Exception ioe){
                ioe.printStackTrace();
                ioe.printStackTrace(response.getWriter()); 
            }
       }
    
      private String validateCaptcha(String secret, String response, String remoteip) throws IOException
      {
        URLConnection connection = null;
        InputStream is = null;
        String output = "";
        String proxyHost = "YOUR_PROXY_NAME";
        int proxyPort = 80; //proxy server port, generally 80 or 443 (confirm from sys-admin)
        SocketAddress addr = new InetSocketAddress(proxyHost, proxyPort);
        Proxy httpProxy = new Proxy(Proxy.Type.HTTP, addr);
    
        String filename = System.getProperty("java.home") + "/lib/security/cacerts".replace('/', File.separatorChar);
        String password = "changeit";
        System.setProperty("javax.net.ssl.trustStore",filename);
        System.setProperty("javax.net.ssl.trustAnchors",filename); 
        System.setProperty("javax.net.ssl.trustStorePassword",password);
    
          String charset = Charset.forName("UTF-8").name();
          String url = "https://www.google.com/recaptcha/api/siteverify";
          try {            
              String query = String.format("secret=%s&response=%s&remoteip=%s", 
              URLEncoder.encode(secret, charset),
              URLEncoder.encode(response, charset),
              URLEncoder.encode(remoteip, charset));
    
              URL fullURL = new URL(url + "?" + query);
              connection = fullURL.openConnection(httpProxy);
              connection.addRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0");
              is = connection.getInputStream();
              System.out.println("connection InputStream");
                      BufferedReader reader = null;
                      String responseXXX = "";
                      reader = new BufferedReader(new InputStreamReader(is));
                      responseXXX = reader.readLine();
                      while (responseXXX!=null) {
                          output+= responseXXX;
                          responseXXX = reader.readLine();
                      }   
              System.out.println("Output: " + output);
          }
          finally {
              if (is != null) {
                  try {
                      is.close();
                  } catch (IOException e) {
                      //cannot do anything here
                  }
              }
          }
          return output;
      }
    }