diff --git a/airsonic-main/pom.xml b/airsonic-main/pom.xml old mode 100644 new mode 100755 index ba26cc0e..2c66531a --- a/airsonic-main/pom.xml +++ b/airsonic-main/pom.xml @@ -323,18 +323,18 @@ 1.1.0 - - net.tanesha.recaptcha4j - recaptcha4j - 0.0.8 - - de.u-mass lastfm-java 0.1.2 + + de.triology.recaptchav2-java + recaptchav2-java + 1.0.2 + + org.apache.cxf diff --git a/airsonic-main/src/main/java/org/airsonic/player/command/AdvancedSettingsCommand.java b/airsonic-main/src/main/java/org/airsonic/player/command/AdvancedSettingsCommand.java index 71e44cc4..ab11386e 100644 --- a/airsonic-main/src/main/java/org/airsonic/player/command/AdvancedSettingsCommand.java +++ b/airsonic-main/src/main/java/org/airsonic/player/command/AdvancedSettingsCommand.java @@ -45,6 +45,10 @@ public class AdvancedSettingsCommand { private String smtpPassword; private String smtpFrom; + private boolean captchaEnabled; + private String recaptchaSiteKey; + private String recaptchaSecretKey; + public String getDownloadLimit() { return downloadLimit; } @@ -167,4 +171,28 @@ public class AdvancedSettingsCommand { public void setSmtpFrom(String smtpFrom) { this.smtpFrom = smtpFrom; } + + public boolean isCaptchaEnabled() { + return captchaEnabled; + } + + public void setCaptchaEnabled(boolean captchaEnabled) { + this.captchaEnabled = captchaEnabled; + } + + public String getRecaptchaSiteKey() { + return recaptchaSiteKey; + } + + public void setRecaptchaSiteKey(String recaptchaSiteKey) { + this.recaptchaSiteKey = recaptchaSiteKey; + } + + public String getRecaptchaSecretKey() { + return recaptchaSecretKey; + } + + public void setRecaptchaSecretKey(String recaptchaSecretKey) { + this.recaptchaSecretKey = recaptchaSecretKey; + } } diff --git a/airsonic-main/src/main/java/org/airsonic/player/controller/AdvancedSettingsController.java b/airsonic-main/src/main/java/org/airsonic/player/controller/AdvancedSettingsController.java index a682bedd..96f9864f 100644 --- a/airsonic-main/src/main/java/org/airsonic/player/controller/AdvancedSettingsController.java +++ b/airsonic-main/src/main/java/org/airsonic/player/controller/AdvancedSettingsController.java @@ -61,6 +61,9 @@ public class AdvancedSettingsController { command.setSmtpUser(settingsService.getSmtpUser()); command.setSmtpFrom(settingsService.getSmtpFrom()); + command.setCaptchaEnabled(settingsService.isCaptchaEnabled()); + command.setRecaptchaSiteKey(settingsService.getRecaptchaSiteKey()); + model.addAttribute("command", command); return "advancedSettings"; } @@ -98,6 +101,12 @@ public class AdvancedSettingsController { settingsService.setSmtpPassword(command.getSmtpPassword()); } + settingsService.setCaptchaEnabled(command.isCaptchaEnabled()); + settingsService.setRecaptchaSiteKey(command.getRecaptchaSiteKey()); + if (StringUtils.isNotEmpty(command.getRecaptchaSecretKey())) { + settingsService.setRecaptchaSecretKey(command.getRecaptchaSecretKey()); + } + settingsService.save(); return "redirect:advancedSettings.view"; diff --git a/airsonic-main/src/main/java/org/airsonic/player/controller/RecoverController.java b/airsonic-main/src/main/java/org/airsonic/player/controller/RecoverController.java index a05ad05a..e095b349 100644 --- a/airsonic-main/src/main/java/org/airsonic/player/controller/RecoverController.java +++ b/airsonic-main/src/main/java/org/airsonic/player/controller/RecoverController.java @@ -1,8 +1,6 @@ package org.airsonic.player.controller; -import net.tanesha.recaptcha.ReCaptcha; -import net.tanesha.recaptcha.ReCaptchaFactory; -import net.tanesha.recaptcha.ReCaptchaResponse; +import de.triology.recaptchav2java.ReCaptcha; import org.airsonic.player.domain.User; import org.airsonic.player.service.SecurityService; import org.airsonic.player.service.SettingsService; @@ -49,19 +47,22 @@ public class RecoverController { Map map = new HashMap(); String usernameOrEmail = StringUtils.trimToNull(request.getParameter("usernameOrEmail")); - ReCaptcha captcha = ReCaptchaFactory.newSecureReCaptcha("6LcZ3OMSAAAAANkKMdFdaNopWu9iS03V-nLOuoiH", - "6LcZ3OMSAAAAAPaFg89mEzs-Ft0fIu7wxfKtkwmQ", false); - boolean showCaptcha = true; if (usernameOrEmail != null) { map.put("usernameOrEmail", usernameOrEmail); User user = getUserByUsernameOrEmail(usernameOrEmail); - String challenge = request.getParameter("recaptcha_challenge_field"); - String uresponse = request.getParameter("recaptcha_response_field"); - ReCaptchaResponse captchaResponse = captcha.checkAnswer(request.getRemoteAddr(), challenge, uresponse); - if (!captchaResponse.isValid()) { + boolean captchaOk; + if (settingsService.isCaptchaEnabled()) { + String recaptchaResponse = request.getParameter("g-recaptcha-response"); + ReCaptcha captcha = new ReCaptcha(settingsService.getRecaptchaSecretKey()); + captchaOk = recaptchaResponse != null && captcha.isValid(recaptchaResponse); + } else { + captchaOk = true; + } + + if (!captchaOk) { map.put("error", "recover.error.invalidcaptcha"); } else if (user == null) { map.put("error", "recover.error.usernotfound"); @@ -74,15 +75,14 @@ public class RecoverController { user.setLdapAuthenticated(false); user.setPassword(password); securityService.updateUser(user); - showCaptcha = false; } else { map.put("error", "recover.error.sendfailed"); } } } - if (showCaptcha) { - map.put("captcha", captcha.createRecaptchaHtml(null, null)); + if (settingsService.isCaptchaEnabled()) { + map.put("recaptchaSiteKey", settingsService.getRecaptchaSiteKey()); } return new ModelAndView("recover", "model", map); diff --git a/airsonic-main/src/main/java/org/airsonic/player/service/SettingsService.java b/airsonic-main/src/main/java/org/airsonic/player/service/SettingsService.java index c9463280..1ba3702f 100644 --- a/airsonic-main/src/main/java/org/airsonic/player/service/SettingsService.java +++ b/airsonic-main/src/main/java/org/airsonic/player/service/SettingsService.java @@ -117,6 +117,10 @@ public class SettingsService { private static final String KEY_IGNORE_SYMLINKS = "IgnoreSymLinks"; private static final String KEY_EXCLUDE_PATTERN_STRING = "ExcludePattern"; + private static final String KEY_CAPTCHA_ENABLED = "CaptchaEnabled"; + private static final String KEY_RECAPTCHA_SITE_KEY = "ReCaptchaSiteKey"; + private static final String KEY_RECAPTCHA_SECRET_KEY = "ReCaptchaSecretKey"; + // Database Settings private static final String KEY_DATABASE_CONFIG_TYPE = "DatabaseConfigType"; private static final String KEY_DATABASE_CONFIG_EMBED_DRIVER = "DatabaseConfigEmbedDriver"; @@ -193,6 +197,10 @@ public class SettingsService { private static final String DEFAULT_SMTP_PASSWORD = null; private static final String DEFAULT_SMTP_FROM = "airsonic@airsonic.org"; + private static final boolean DEFAULT_CAPTCHA_ENABLED = false; + private static final String DEFAULT_RECAPTCHA_SITE_KEY = "6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI"; + private static final String DEFAULT_RECAPTCHA_SECRET_KEY = "6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe"; + private static final DataSourceConfigType DEFAULT_DATABASE_CONFIG_TYPE = DataSourceConfigType.LEGACY; private static final String DEFAULT_DATABASE_CONFIG_EMBED_DRIVER = null; private static final String DEFAULT_DATABASE_CONFIG_EMBED_URL = null; @@ -1311,6 +1319,30 @@ public class SettingsService { setString(KEY_SMTP_FROM, smtpFrom); } + public boolean isCaptchaEnabled() { + return getBoolean(KEY_CAPTCHA_ENABLED, DEFAULT_CAPTCHA_ENABLED); + } + + public void setCaptchaEnabled(boolean captchaEnabled) { + setBoolean(KEY_CAPTCHA_ENABLED, captchaEnabled); + } + + public String getRecaptchaSiteKey() { + return getProperty(KEY_RECAPTCHA_SITE_KEY, DEFAULT_RECAPTCHA_SITE_KEY); + } + + public void setRecaptchaSiteKey(String recaptchaSiteKey) { + setString(KEY_RECAPTCHA_SITE_KEY, recaptchaSiteKey); + } + + public String getRecaptchaSecretKey() { + return getProperty(KEY_RECAPTCHA_SECRET_KEY, DEFAULT_RECAPTCHA_SECRET_KEY); + } + + public void setRecaptchaSecretKey(String recaptchaSecretKey) { + setString(KEY_RECAPTCHA_SECRET_KEY, recaptchaSecretKey); + } + public DataSourceConfigType getDatabaseConfigType() { String raw = getString(KEY_DATABASE_CONFIG_TYPE, DEFAULT_DATABASE_CONFIG_TYPE.name()); return DataSourceConfigType.valueOf(StringUtils.upperCase(raw)); diff --git a/airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_en.properties b/airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_en.properties index b14e9356..09831897 100644 --- a/airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_en.properties +++ b/airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_en.properties @@ -338,6 +338,9 @@ advancedsettings.smtpEncryption.none=None advancedsettings.smtpEncryption.starttls=STARTTLS advancedsettings.smtpEncryption.ssl=SSL/TLS advancedsettings.smtpFrom=E-mail sender +advancedsettings.enableCaptcha=Require CAPTCHA for account recovery +advancedsettings.recaptchaSiteKey=reCAPTCHA site key +advancedsettings.recaptchaSecretKey=reCAPTCHA secret key # personalSettings.jsp personalsettings.title=Personal settings for {0} personalsettings.language=Language @@ -730,6 +733,12 @@ helppopup.smtpEncryption.title=SMTP Encryption helppopup.smtpEncryption.text=

Encryption method used for connections to the SMTP server. Choose "None" for no encryption.

helppopup.smtpFrom.title=From address helppopup.smtpFrom.text=

The sender address for e-mails originating from the Airsonic server. Must be a valid e-mail address.

+helppopup.captcha.title=CAPTCHA +helppopup.captcha.text=

When enabled, users must solve a CAPTCHA to prove they are human when requesting a password reset.

Requires registration with an external service; see the documentation.

+helppopup.recaptchaSiteKey.title=reCAPTCHA site key +helppopup.recaptchaSiteKey.text=

A site key obtained from the reCAPTCHA admin console.

+helppopup.recaptchaSecretKey.title=reCAPTCHA secret key +helppopup.recaptchaSecretKey.text=

A secret key obtained from the reCAPTCHA admin console. Left unchanged if blank.

helppopup.scanMediaFolders.title=Media folders scanning rules helppopup.scanMediaFolders.text=

Note that subfolder names starting with a dot (.) or @eaDir, as well as Thumbs.db files, are ignored.

# wap/index.jsp diff --git a/airsonic-main/src/main/webapp/WEB-INF/jsp/advancedSettings.jsp b/airsonic-main/src/main/webapp/WEB-INF/jsp/advancedSettings.jsp index 66937f7a..42fb932e 100644 --- a/airsonic-main/src/main/webapp/WEB-INF/jsp/advancedSettings.jsp +++ b/airsonic-main/src/main/webapp/WEB-INF/jsp/advancedSettings.jsp @@ -91,7 +91,34 @@ + + + + + + + + + + + + + + +
+ + + +
+ + +
+ + +
@@ -152,4 +179,4 @@ - \ No newline at end of file + diff --git a/airsonic-main/src/main/webapp/WEB-INF/jsp/recover.jsp b/airsonic-main/src/main/webapp/WEB-INF/jsp/recover.jsp index dbcdc7e7..ff26a610 100644 --- a/airsonic-main/src/main/webapp/WEB-INF/jsp/recover.jsp +++ b/airsonic-main/src/main/webapp/WEB-INF/jsp/recover.jsp @@ -21,9 +21,10 @@ "> - +

- + +

diff --git a/repo/net/tanesha/recaptcha4j/recaptcha4j/0.0.8/recaptcha4j-0.0.8-sources.jar b/repo/net/tanesha/recaptcha4j/recaptcha4j/0.0.8/recaptcha4j-0.0.8-sources.jar deleted file mode 100644 index ce7c4bc1..00000000 Binary files a/repo/net/tanesha/recaptcha4j/recaptcha4j/0.0.8/recaptcha4j-0.0.8-sources.jar and /dev/null differ diff --git a/repo/net/tanesha/recaptcha4j/recaptcha4j/0.0.8/recaptcha4j-0.0.8.jar b/repo/net/tanesha/recaptcha4j/recaptcha4j/0.0.8/recaptcha4j-0.0.8.jar deleted file mode 100644 index 03460d70..00000000 Binary files a/repo/net/tanesha/recaptcha4j/recaptcha4j/0.0.8/recaptcha4j-0.0.8.jar and /dev/null differ diff --git a/repo/net/tanesha/recaptcha4j/recaptcha4j/0.0.8/recaptcha4j-0.0.8.pom b/repo/net/tanesha/recaptcha4j/recaptcha4j/0.0.8/recaptcha4j-0.0.8.pom deleted file mode 100644 index 4090c285..00000000 --- a/repo/net/tanesha/recaptcha4j/recaptcha4j/0.0.8/recaptcha4j-0.0.8.pom +++ /dev/null @@ -1,6 +0,0 @@ - - 4.0.0 - net.tanesha.recaptcha4j - recaptcha4j - 0.0.8 - \ No newline at end of file