Add settings for CAPTCHA in account recovery.

Allowing users to enable it and specify the site and secret key to use
with reCAPTCHA.

The old hard-coded keys were insecure; the secret key must not be
distributed publicly. The current defaults are the test keys provided at
https://developers.google.com/recaptcha/docs/faq#id-like-to-run-automated-tests-with-recaptcha-v2-what-should-i-do

Signed-off-by: Peter Marheine <peter@taricorp.net>
master
Peter Marheine 6 years ago
parent 749342f25e
commit a928b9ee3f
  1. 28
      airsonic-main/src/main/java/org/airsonic/player/command/AdvancedSettingsCommand.java
  2. 9
      airsonic-main/src/main/java/org/airsonic/player/controller/AdvancedSettingsController.java
  3. 32
      airsonic-main/src/main/java/org/airsonic/player/service/SettingsService.java
  4. 9
      airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_en.properties
  5. 27
      airsonic-main/src/main/webapp/WEB-INF/jsp/advancedSettings.jsp

@ -45,6 +45,10 @@ public class AdvancedSettingsCommand {
private String smtpPassword; private String smtpPassword;
private String smtpFrom; private String smtpFrom;
private boolean captchaEnabled;
private String recaptchaSiteKey;
private String recaptchaSecretKey;
public String getDownloadLimit() { public String getDownloadLimit() {
return downloadLimit; return downloadLimit;
} }
@ -167,4 +171,28 @@ public class AdvancedSettingsCommand {
public void setSmtpFrom(String smtpFrom) { public void setSmtpFrom(String smtpFrom) {
this.smtpFrom = 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;
}
} }

@ -61,6 +61,9 @@ public class AdvancedSettingsController {
command.setSmtpUser(settingsService.getSmtpUser()); command.setSmtpUser(settingsService.getSmtpUser());
command.setSmtpFrom(settingsService.getSmtpFrom()); command.setSmtpFrom(settingsService.getSmtpFrom());
command.setCaptchaEnabled(settingsService.isCaptchaEnabled());
command.setRecaptchaSiteKey(settingsService.getRecaptchaSiteKey());
model.addAttribute("command", command); model.addAttribute("command", command);
return "advancedSettings"; return "advancedSettings";
} }
@ -98,6 +101,12 @@ public class AdvancedSettingsController {
settingsService.setSmtpPassword(command.getSmtpPassword()); settingsService.setSmtpPassword(command.getSmtpPassword());
} }
settingsService.setCaptchaEnabled(command.isCaptchaEnabled());
settingsService.setRecaptchaSiteKey(command.getRecaptchaSiteKey());
if (StringUtils.isNotEmpty(command.getRecaptchaSecretKey())) {
settingsService.setRecaptchaSecretKey(command.getRecaptchaSecretKey());
}
settingsService.save(); settingsService.save();
return "redirect:advancedSettings.view"; return "redirect:advancedSettings.view";

@ -117,6 +117,10 @@ public class SettingsService {
private static final String KEY_IGNORE_SYMLINKS = "IgnoreSymLinks"; private static final String KEY_IGNORE_SYMLINKS = "IgnoreSymLinks";
private static final String KEY_EXCLUDE_PATTERN_STRING = "ExcludePattern"; 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 // Database Settings
private static final String KEY_DATABASE_CONFIG_TYPE = "DatabaseConfigType"; private static final String KEY_DATABASE_CONFIG_TYPE = "DatabaseConfigType";
private static final String KEY_DATABASE_CONFIG_EMBED_DRIVER = "DatabaseConfigEmbedDriver"; 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_PASSWORD = null;
private static final String DEFAULT_SMTP_FROM = "airsonic@airsonic.org"; 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 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_DRIVER = null;
private static final String DEFAULT_DATABASE_CONFIG_EMBED_URL = null; private static final String DEFAULT_DATABASE_CONFIG_EMBED_URL = null;
@ -1311,6 +1319,30 @@ public class SettingsService {
setString(KEY_SMTP_FROM, smtpFrom); 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() { public DataSourceConfigType getDatabaseConfigType() {
String raw = getString(KEY_DATABASE_CONFIG_TYPE, DEFAULT_DATABASE_CONFIG_TYPE.name()); String raw = getString(KEY_DATABASE_CONFIG_TYPE, DEFAULT_DATABASE_CONFIG_TYPE.name());
return DataSourceConfigType.valueOf(StringUtils.upperCase(raw)); return DataSourceConfigType.valueOf(StringUtils.upperCase(raw));

@ -338,6 +338,9 @@ advancedsettings.smtpEncryption.none=None
advancedsettings.smtpEncryption.starttls=STARTTLS advancedsettings.smtpEncryption.starttls=STARTTLS
advancedsettings.smtpEncryption.ssl=SSL/TLS advancedsettings.smtpEncryption.ssl=SSL/TLS
advancedsettings.smtpFrom=E-mail sender 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.jsp
personalsettings.title=Personal settings for {0} personalsettings.title=Personal settings for {0}
personalsettings.language=Language personalsettings.language=Language
@ -730,6 +733,12 @@ helppopup.smtpEncryption.title=SMTP Encryption
helppopup.smtpEncryption.text=<p>Encryption method used for connections to the SMTP server. Choose "None" for no encryption.</p> helppopup.smtpEncryption.text=<p>Encryption method used for connections to the SMTP server. Choose "None" for no encryption.</p>
helppopup.smtpFrom.title=From address helppopup.smtpFrom.title=From address
helppopup.smtpFrom.text=<p>The sender address for e-mails originating from the Airsonic server. Must be a valid e-mail address.</p> helppopup.smtpFrom.text=<p>The sender address for e-mails originating from the Airsonic server. Must be a valid e-mail address.</p>
helppopup.captcha.title=CAPTCHA
helppopup.captcha.text=<p>When enabled, users must solve a CAPTCHA to prove they are human when requesting a password reset.</p> <p>Requires registration with an external service; see the <a href="https://airsonic.github.io/docs/captcha/">documentation</a>.</p>
helppopup.recaptchaSiteKey.title=reCAPTCHA site key
helppopup.recaptchaSiteKey.text=<p>A site key obtained from the reCAPTCHA admin console.</p>
helppopup.recaptchaSecretKey.title=reCAPTCHA secret key
helppopup.recaptchaSecretKey.text=<p>A secret key obtained from the reCAPTCHA admin console. Left unchanged if blank.</p>
helppopup.scanMediaFolders.title=Media folders scanning rules helppopup.scanMediaFolders.title=Media folders scanning rules
helppopup.scanMediaFolders.text=<p>Note that subfolder names starting with a dot (.) or @eaDir, as well as Thumbs.db files, are ignored.</p> helppopup.scanMediaFolders.text=<p>Note that subfolder names starting with a dot (.) or @eaDir, as well as Thumbs.db files, are ignored.</p>
# wap/index.jsp # wap/index.jsp

@ -91,7 +91,34 @@
<c:import url="helpToolTip.jsp"><c:param name="topic" value="smtpCredentials"/></c:import> <c:import url="helpToolTip.jsp"><c:param name="topic" value="smtpCredentials"/></c:import>
</td> </td>
</tr> </tr>
</table>
<table class="indent">
<tr>
<td colspan="2">
<form:checkbox path="captchaEnabled" id="enablecaptcha" cssclass="checkbox"/>
<label for="enablecaptcha">
<fmt:message key="advancedsettings.enableCaptcha"/>
</label>
<c:import url="helpToolTip.jsp"><c:param name="topic" value="captcha"/></c:import>
</td>
</tr>
<tr>
<td><fmt:message key="advancedsettings.recaptchaSiteKey"/></td>
<td>
<form:input path="recaptchaSiteKey" size="50"/>
<c:import url="helpToolTip.jsp"><c:param name="topic" value="recaptchaSiteKey"/></c:import>
</td>
</tr>
<tr>
<td><fmt:message key="advancedsettings.recaptchaSecretKey"/></td>
<td>
<form:input path="recaptchaSecretKey" size="50"/>
<c:import url="helpToolTip.jsp"><c:param name="topic" value="recaptchaSecretKey"/></c:import>
</td>
</tr>
</table> </table>
<table class="indent"><tr><td> <table class="indent"><tr><td>

Loading…
Cancel
Save