001
014
015 package com.liferay.portal.captcha.recaptcha;
016
017 import com.liferay.portal.captcha.simplecaptcha.SimpleCaptchaImpl;
018 import com.liferay.portal.kernel.captcha.CaptchaConfigurationException;
019 import com.liferay.portal.kernel.captcha.CaptchaException;
020 import com.liferay.portal.kernel.captcha.CaptchaTextException;
021 import com.liferay.portal.kernel.exception.SystemException;
022 import com.liferay.portal.kernel.json.JSONArray;
023 import com.liferay.portal.kernel.json.JSONException;
024 import com.liferay.portal.kernel.json.JSONFactoryUtil;
025 import com.liferay.portal.kernel.json.JSONObject;
026 import com.liferay.portal.kernel.log.Log;
027 import com.liferay.portal.kernel.log.LogFactoryUtil;
028 import com.liferay.portal.kernel.util.Http;
029 import com.liferay.portal.kernel.util.HttpUtil;
030 import com.liferay.portal.kernel.util.ParamUtil;
031 import com.liferay.portal.kernel.util.PortalUtil;
032 import com.liferay.portal.kernel.util.PropsKeys;
033 import com.liferay.portal.kernel.util.StringBundler;
034 import com.liferay.portal.kernel.util.StringPool;
035 import com.liferay.portal.kernel.util.StringUtil;
036 import com.liferay.portal.kernel.util.Validator;
037 import com.liferay.portal.util.PrefsPropsUtil;
038 import com.liferay.portal.util.PropsValues;
039
040 import java.io.IOException;
041
042 import javax.portlet.PortletRequest;
043 import javax.portlet.ResourceRequest;
044 import javax.portlet.ResourceResponse;
045
046 import javax.servlet.http.HttpServletRequest;
047 import javax.servlet.http.HttpServletRequestWrapper;
048 import javax.servlet.http.HttpServletResponse;
049
050
056 public class ReCaptchaImpl extends SimpleCaptchaImpl {
057
058 @Override
059 public String getTaglibPath() {
060 return _TAGLIB_PATH;
061 }
062
063 @Override
064 public void serveImage(
065 HttpServletRequest request, HttpServletResponse response) {
066
067 throw new UnsupportedOperationException();
068 }
069
070 @Override
071 public void serveImage(
072 ResourceRequest resourceRequest, ResourceResponse resourceResponse) {
073
074 throw new UnsupportedOperationException();
075 }
076
077 @Override
078 protected boolean validateChallenge(HttpServletRequest request)
079 throws CaptchaException {
080
081 String reCaptchaResponse = ParamUtil.getString(
082 request, "g-recaptcha-response");
083
084 while (Validator.isBlank(reCaptchaResponse) &&
085 (request instanceof HttpServletRequestWrapper)) {
086
087 HttpServletRequestWrapper httpServletRequestWrapper =
088 (HttpServletRequestWrapper)request;
089
090 request =
091 (HttpServletRequest)httpServletRequestWrapper.getRequest();
092
093 reCaptchaResponse = ParamUtil.getString(
094 request, "g-recaptcha-response");
095 }
096
097 if (Validator.isBlank(reCaptchaResponse)) {
098 _log.error(
099 "CAPTCHA text is null. User " + request.getRemoteUser() +
100 " may be trying to circumvent the CAPTCHA.");
101
102 throw new CaptchaTextException();
103 }
104
105 Http.Options options = new Http.Options();
106
107 try {
108 options.addPart(
109 "secret",
110 PrefsPropsUtil.getString(
111 PropsKeys.CAPTCHA_ENGINE_RECAPTCHA_KEY_PRIVATE,
112 PropsValues.CAPTCHA_ENGINE_RECAPTCHA_KEY_PRIVATE));
113 }
114 catch (SystemException se) {
115 _log.error(se, se);
116 }
117
118 options.addPart("remoteip", request.getRemoteAddr());
119 options.addPart("response", reCaptchaResponse);
120 options.setLocation(PropsValues.CAPTCHA_ENGINE_RECAPTCHA_URL_VERIFY);
121 options.setPost(true);
122
123 String content = null;
124
125 try {
126 content = HttpUtil.URLtoString(options);
127 }
128 catch (IOException ioe) {
129 _log.error(ioe, ioe);
130
131 throw new CaptchaConfigurationException();
132 }
133
134 if (content == null) {
135 _log.error("reCAPTCHA did not return a result");
136
137 throw new CaptchaConfigurationException();
138 }
139
140 try {
141 JSONObject jsonObject = JSONFactoryUtil.createJSONObject(content);
142
143 String success = jsonObject.getString("success");
144
145 if (StringUtil.equalsIgnoreCase(success, "true")) {
146 return true;
147 }
148
149 JSONArray jsonArray = jsonObject.getJSONArray("error-codes");
150
151 if ((jsonArray == null) || (jsonArray.length() == 0)) {
152 _log.error("reCAPTCHA encountered an error");
153
154 throw new CaptchaConfigurationException();
155 }
156
157 StringBundler sb = new StringBundler(jsonArray.length() * 2 - 1);
158
159 for (int i = 0; i < jsonArray.length(); i++) {
160 sb.append(jsonArray.getString(i));
161
162 if (i < (jsonArray.length() - 1)) {
163 sb.append(StringPool.COMMA_AND_SPACE);
164 }
165 }
166
167 _log.error("reCAPTCHA encountered an error: " + sb.toString());
168
169 throw new CaptchaConfigurationException();
170 }
171 catch (JSONException jsone) {
172 _log.error("reCAPTCHA did not return a valid result: " + content);
173
174 throw new CaptchaConfigurationException();
175 }
176 }
177
178 @Override
179 protected boolean validateChallenge(PortletRequest portletRequest)
180 throws CaptchaException {
181
182 HttpServletRequest request = PortalUtil.getHttpServletRequest(
183 portletRequest);
184
185 return validateChallenge(request);
186 }
187
188 private static final String _TAGLIB_PATH =
189 "/html/taglib/ui/captcha/recaptcha.jsp";
190
191 private static final Log _log = LogFactoryUtil.getLog(ReCaptchaImpl.class);
192
193 }