Commit 07a38856 authored by Matija Obreza's avatar Matija Obreza
Browse files

Extracted ReCaptchaUtil for use in user registration and germplasm

requests.
Updated EasySMTA connector to latest development version.
parent 01f76b17
...@@ -94,7 +94,7 @@ public interface AccessionRepository extends JpaRepository<Accession, Long> { ...@@ -94,7 +94,7 @@ public interface AccessionRepository extends JpaRepository<Accession, Long> {
Accession findByInstituteCodeAndAccessionNameAndGenus(String holdingInstitute, String accessionName, String genus); Accession findByInstituteCodeAndAccessionNameAndGenus(String holdingInstitute, String accessionName, String genus);
@Query("select count(a.id) from Accession a where a.id in ( ?1 ) and a.availability = 'Y'") @Query("select count(a.id) from Accession a where a.id in ( ?1 ) and a.availability = true")
long countAvailable(Set<Long> accessionIds); long countAvailable(Set<Long> accessionIds);
} }
...@@ -2,16 +2,22 @@ package org.genesys2.server.service.impl; ...@@ -2,16 +2,22 @@ package org.genesys2.server.service.impl;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpEntity; import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse; import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException; import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient; import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet; import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
...@@ -22,10 +28,8 @@ import com.fasterxml.jackson.databind.ObjectMapper; ...@@ -22,10 +28,8 @@ import com.fasterxml.jackson.databind.ObjectMapper;
public class EasySMTAConnector { public class EasySMTAConnector {
private static final Log LOG = LogFactory.getLog(EasySMTAConnector.class); private static final Log LOG = LogFactory.getLog(EasySMTAConnector.class);
// FIXME Use the safe URL @Value("${itpgrfa.easysmta.url}")
// private static final String ITPGRFA_PID_URL = private String serverUrl;
// "https://www.itworks.it/itt/index.php?r=extsys/getUserDetails2";
private static final String ITPGRFA_PID_URL = "https://www.itworks.it/itt/index.php?r=extsys/getUserDetails2&esUsername=XXX&esPassword=YYY&usEmail=ZZZ";
@Value("${itpgrfa.easysmta.username}") @Value("${itpgrfa.easysmta.username}")
private String serverUsername; private String serverUsername;
...@@ -36,28 +40,27 @@ public class EasySMTAConnector { ...@@ -36,28 +40,27 @@ public class EasySMTAConnector {
public EasySMTAUserData getUserData(String emailAddress) { public EasySMTAUserData getUserData(String emailAddress) {
final HttpClient httpclient = new DefaultHttpClient(); final HttpClient httpclient = new DefaultHttpClient();
// FIXME Url contains username+password, see below LOG.info("Checking EasySMTA at " + serverUrl + " for email: " + emailAddress);
String url = ITPGRFA_PID_URL.replace("XXX", serverUsername); final HttpPost httpPost = new HttpPost(serverUrl);
url = url.replace("YYY", serverPassword);
url = url.replace("ZZZ", emailAddress);
LOG.warn("Using unsafe fetch URL: " + url); List<NameValuePair> nvps = new ArrayList<NameValuePair>();
nvps.add(new BasicNameValuePair("esUsername", serverUsername));
nvps.add(new BasicNameValuePair("esPassword", serverPassword));
nvps.add(new BasicNameValuePair("usEmail", emailAddress));
try {
httpPost.setEntity(new UrlEncodedFormEntity(nvps));
} catch (UnsupportedEncodingException e1) {
LOG.error(e1, e1);
return null;
}
final HttpGet httpget = new HttpGet(url);
HttpResponse response = null; HttpResponse response = null;
BufferedReader br = null; BufferedReader br = null;
try { try {
LOG.info("Using " + serverUsername + " as Easy-SMTA username."); LOG.info("Using " + serverUsername + " as Easy-SMTA username.");
// FIXME Use these when Easy-SMTA is fixed response = httpclient.execute(httpPost);
// httpclient.getParams().setParameter("esUsername",
// serverUsername);
// httpclient.getParams().setParameter("esPassword",
// serverPassword);
// httpclient.getParams().setParameter("usEmail", emailAddress);
response = httpclient.execute(httpget);
// Get hold of the response entity // Get hold of the response entity
final HttpEntity entity = response.getEntity(); final HttpEntity entity = response.getEntity();
...@@ -68,7 +71,7 @@ public class EasySMTAConnector { ...@@ -68,7 +71,7 @@ public class EasySMTAConnector {
if (entity != null) { if (entity != null) {
ObjectMapper objectMapper = new ObjectMapper(); ObjectMapper objectMapper = new ObjectMapper();
JsonNode tree = objectMapper.readTree(entity.getContent()); JsonNode tree = objectMapper.readTree(entity.getContent());
LOG.debug(tree); LOG.info("EasySMTA: " + tree);
if (tree.has("errorCode")) { if (tree.has("errorCode")) {
// Check failed // Check failed
...@@ -78,10 +81,6 @@ public class EasySMTAConnector { ...@@ -78,10 +81,6 @@ public class EasySMTAConnector {
} else { } else {
if (LOG.isDebugEnabled()) {
LOG.debug(tree);
}
return new EasySMTAUserData(tree.get("pid").asText(), tree.get("name").asText(), tree.get("surname").asText(), tree.get("email").asText(), return new EasySMTAUserData(tree.get("pid").asText(), tree.get("name").asText(), tree.get("surname").asText(), tree.get("email").asText(),
tree.get("orgName").asText(), tree.get("country").asText()); tree.get("orgName").asText(), tree.get("country").asText());
} }
...@@ -93,7 +92,7 @@ public class EasySMTAConnector { ...@@ -93,7 +92,7 @@ public class EasySMTAConnector {
LOG.error(e); LOG.error(e);
} finally { } finally {
IOUtils.closeQuietly(br); IOUtils.closeQuietly(br);
httpget.releaseConnection(); httpPost.releaseConnection();
LOG.debug("EasySMTA streams closed."); LOG.debug("EasySMTA streams closed.");
} }
...@@ -124,7 +123,7 @@ public class EasySMTAConnector { ...@@ -124,7 +123,7 @@ public class EasySMTAConnector {
@Override @Override
public String toString() { public String toString() {
return "PID " + firstName + " " + lastName + ", " + organization + ", country=" + countryIsoCode3; return "ITPGRFA.PID email=" + email + " first=" + firstName + " last=" + lastName + ", org=" + organization + ", country=" + countryIsoCode3;
} }
} }
} }
...@@ -16,22 +16,18 @@ ...@@ -16,22 +16,18 @@
package org.genesys2.server.servlet.controller; package org.genesys2.server.servlet.controller;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import net.tanesha.recaptcha.ReCaptchaImpl;
import net.tanesha.recaptcha.ReCaptchaResponse;
import org.genesys2.server.model.Permissions; import org.genesys2.server.model.Permissions;
import org.genesys2.server.model.UserRole; import org.genesys2.server.model.UserRole;
import org.genesys2.server.model.impl.User; import org.genesys2.server.model.impl.User;
import org.genesys2.server.service.ContentService; import org.genesys2.server.service.ContentService;
import org.genesys2.server.service.CropService; import org.genesys2.server.service.CropService;
import org.genesys2.server.service.UserService; import org.genesys2.server.service.UserService;
import org.genesys2.util.ReCaptchaUtil;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
...@@ -105,28 +101,10 @@ public class HtmlController extends BaseController { ...@@ -105,28 +101,10 @@ public class HtmlController extends BaseController {
validator.validate(user, bindingResult); validator.validate(user, bindingResult);
// Validate the reCAPTCHA // Validate the reCAPTCHA
String remoteAddr = req.getRemoteAddr(); if (!ReCaptchaUtil.isValid(captchaPrivateKey, req.getRemoteAddr(), challenge, response)) {
boolean isLocalRequest = false; _logger.warn("Invalid captcha.");
FieldError fieldError = new FieldError("comment", "captcha", response, false, new String[] { "errors.badCaptcha" }, null, "Please try again.");
try { bindingResult.addError(fieldError);
InetAddress remoteInetAddr = InetAddress.getByName(remoteAddr);
isLocalRequest = remoteInetAddr.isLinkLocalAddress() || remoteInetAddr.isAnyLocalAddress() || remoteInetAddr.isLoopbackAddress();
_logger.warn("Remote addr: " + remoteAddr + " " + remoteInetAddr + " isLocal=" + isLocalRequest);
} catch (UnknownHostException e1) {
_logger.warn(e1.getMessage());
}
if (!isLocalRequest) {
ReCaptchaImpl reCaptcha = new ReCaptchaImpl();
reCaptcha.setPrivateKey(captchaPrivateKey);
ReCaptchaResponse reCaptchaResponse = reCaptcha.checkAnswer(remoteAddr, challenge, response);
if (!reCaptchaResponse.isValid()) {
_logger.warn("Invalid captcha.");
FieldError fieldError = new FieldError("comment", "captcha", response, false, new String[] { "errors.badCaptcha" }, null, "Please try again.");
bindingResult.addError(fieldError);
}
} }
try { try {
......
...@@ -16,12 +16,16 @@ ...@@ -16,12 +16,16 @@
package org.genesys2.server.servlet.controller; package org.genesys2.server.servlet.controller;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.genesys2.server.service.ContentService; import org.genesys2.server.service.ContentService;
import org.genesys2.server.service.GenesysService; import org.genesys2.server.service.GenesysService;
import org.genesys2.server.service.impl.EasySMTAConnector; import org.genesys2.server.service.impl.EasySMTAConnector;
import org.genesys2.server.service.impl.EasySMTAConnector.EasySMTAUserData; import org.genesys2.server.service.impl.EasySMTAConnector.EasySMTAUserData;
import org.genesys2.util.ReCaptchaUtil;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort;
...@@ -53,6 +57,12 @@ public class RequestController extends BaseController { ...@@ -53,6 +57,12 @@ public class RequestController extends BaseController {
@Autowired @Autowired
private EasySMTAConnector pidChecker; private EasySMTAConnector pidChecker;
@Value("${captcha.privateKey}")
private String captchaPrivateKey;
@Value("${captcha.publicKey}")
private String captchaPublicKey;
/** /**
* Give information about the request process * Give information about the request process
* *
...@@ -73,18 +83,26 @@ public class RequestController extends BaseController { ...@@ -73,18 +83,26 @@ public class RequestController extends BaseController {
@RequestMapping(method = RequestMethod.POST, value = "/start") @RequestMapping(method = RequestMethod.POST, value = "/start")
public String start(ModelMap model) { public String start(ModelMap model) {
model.addAttribute("blurp", contentService.getGlobalArticle("request-personal", getLocale())); model.addAttribute("blurp", contentService.getGlobalArticle("request-personal", getLocale()));
model.addAttribute("captchaPublicKey", captchaPublicKey);
return "/request/personal"; return "/request/personal";
} }
@RequestMapping(method = RequestMethod.POST, value = "/submit") @RequestMapping(method = RequestMethod.POST, value = "/submit")
public String submit(ModelMap model, @RequestParam(value = "email", defaultValue = "", required = true) String emailAddress) { public String submit(ModelMap model, HttpServletRequest req, @RequestParam(value = "email", defaultValue = "", required = true) String emailAddress, @RequestParam(value = "recaptcha_challenge_field", required = false) String challenge,
@RequestParam(value = "recaptcha_response_field", required = false) String response) {
emailAddress = emailAddress.trim(); emailAddress = emailAddress.trim();
if (StringUtils.isBlank(emailAddress)) { if (StringUtils.isBlank(emailAddress)) {
_logger.warn("No email address was specified for request. Stopping here."); _logger.warn("No email address was specified for request. Stopping here.");
return "/request/personal"; return "/request/personal";
} }
// Validate the reCAPTCHA
if (!ReCaptchaUtil.isValid(captchaPrivateKey, req.getRemoteAddr(), challenge, response)) {
_logger.warn("Recaptcha not valid. Stopping here.");
return "/request/personal";
}
_logger.info("Checking for ITPGRFA PID account for " + emailAddress); _logger.info("Checking for ITPGRFA PID account for " + emailAddress);
EasySMTAUserData pid = pidChecker.getUserData(emailAddress); EasySMTAUserData pid = pidChecker.getUserData(emailAddress);
...@@ -93,7 +111,7 @@ public class RequestController extends BaseController { ...@@ -93,7 +111,7 @@ public class RequestController extends BaseController {
} else { } else {
// TODO send email to registered email address, wait for response // TODO send email to registered email address, wait for response
_logger.info("TODO TODO TODO : Send email to : " + pid); _logger.info("Send email to: " + pid);
} }
......
/**
* Copyright 2013 Global Crop Diversity Trust
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
package org.genesys2.util;
import java.net.InetAddress;
import java.net.UnknownHostException;
import net.tanesha.recaptcha.ReCaptcha;
import net.tanesha.recaptcha.ReCaptchaImpl;
import net.tanesha.recaptcha.ReCaptchaResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* {@link ReCaptcha} wrapper
*
* @author matijaobreza
*
*/
public class ReCaptchaUtil {
private final static Logger _logger = LoggerFactory.getLogger(ReCaptchaUtil.class);
// Validate the reCAPTCHA
public static boolean isValid(String captchaPrivateKey, String remoteAddr, String challenge, String response) {
boolean isLocalRequest = false;
try {
InetAddress remoteInetAddr = InetAddress.getByName(remoteAddr);
isLocalRequest = remoteInetAddr.isLinkLocalAddress() || remoteInetAddr.isAnyLocalAddress() || remoteInetAddr.isLoopbackAddress();
_logger.warn("Remote addr: " + remoteAddr + " " + remoteInetAddr + " isLocal=" + isLocalRequest);
} catch (UnknownHostException e1) {
_logger.warn(e1.getMessage());
}
if (isLocalRequest) {
_logger.info("Ignoring localhost re-captcha.");
return true;
}
ReCaptchaImpl reCaptcha = new ReCaptchaImpl();
reCaptcha.setPrivateKey(captchaPrivateKey);
ReCaptchaResponse reCaptchaResponse = reCaptcha.checkAnswer(remoteAddr, challenge, response);
return reCaptchaResponse.isValid();
}
}
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
#db.username = sa #db.username = sa
#db.password = #db.password =
db.url=jdbc:mysql://127.0.0.1/genesys2?useUnicode=true&characterEncoding=UTF-8&useFastDateParsing=false&autoCommit=false db.url=jdbc:mysql://127.0.0.1/genesys2?useUnicode=true&characterEncoding=UTF-8&useFastDateParsing=false
db.driverClassName = com.mysql.jdbc.Driver db.driverClassName = com.mysql.jdbc.Driver
db.username = root db.username = root
db.password = db.password =
...@@ -42,6 +42,7 @@ captcha.publicKey=6Lf7oucSAAAAAGaS7ObroY2bNgCqMTmpyFVu7wMW ...@@ -42,6 +42,7 @@ captcha.publicKey=6Lf7oucSAAAAAGaS7ObroY2bNgCqMTmpyFVu7wMW
download.files.dir=./data/ download.files.dir=./data/
# ITPGRFA Easy-SMTA account (if you have one) # ITPGRFA Easy-SMTA account (if you have one)
itpgrfa.easysmta.url=
itpgrfa.easysmta.username= itpgrfa.easysmta.username=
itpgrfa.easysmta.password= itpgrfa.easysmta.password=
......
...@@ -20,7 +20,20 @@ ...@@ -20,7 +20,20 @@
<input type="text" name="email" class="span3 required email form-control" /> <input type="text" name="email" class="span3 required email form-control" />
</div> </div>
</div> </div>
<div class="form-group">
<label class="col-lg-2 control-label"><spring:message code="captcha.text" /></label>
<div class="col-lg-3">
<script type="text/javascript" src="http://api.recaptcha.net/challenge?k=${captchaPublicKey}">
</script>
<noscript>
<iframe src="http://api.recaptcha.net/noscript?k=${captchaPublicKey}" height="300" width="500" frameborder="0"></iframe>
<br>
<textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
<input type="hidden" name="recaptcha_response_field" value="manual_challenge">
</noscript>
</div>
</div>
<div class="form-actions"> <div class="form-actions">
<input class="btn btn-primary" type="submit" value="<spring:message code="request.start-request" />" /> <input class="btn btn-primary" type="submit" value="<spring:message code="request.start-request" />" />
</div> </div>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment