在我的新项目中,我将包括google recaptcha。 我的问题相当简单,即使我们做客户端验证用户不是机器人,即使建议进行服务器端验证。 我想知道为什么有必要为google recaptcha进行服务器端验证?它是如何添加额外的安全层的?如何在弹簧安全的春季启动?
答案 0 :(得分:2)
服务器端验证必须!! reCAPTCHA的设计方式是客户端只生成' g-captcha-response'与密钥(存储在服务器端)一起发送到https://www.google.com/recaptcha/api/siteverify进行验证。响应是一个JSON,它声明成功为真或假,并进一步推送到客户端。仅在客户端进行验证在技术上是可行的,但它失败了目的。此外,如果仅进行客户端验证,则可能会在控制台中收到CORS(跨源资源共享)策略错误。我可以分享步骤在servlet中进行简单的基于Java的服务器端验证。如果您需要,请告诉我。
答案 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;
}
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;
}
}