refactor: add validation for initializing super admin username (#3744)

#### What type of PR is this?
/kind improvement
/area core

#### What this PR does / why we need it:
对初始超级管理员用户名增加合法性校验

#### Which issue(s) this PR fixes:
Fixes #3482

#### Does this PR introduce a user-facing change?

```release-note
对初始超级管理员用户名增加合法性校验
```
pull/3819/head
guqing 2023-04-21 11:20:12 +08:00 committed by GitHub
parent 11a5807682
commit f076fc5740
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 106 additions and 2 deletions

View File

@ -0,0 +1,33 @@
package run.halo.app.infra;
import java.util.regex.Pattern;
import lombok.experimental.UtilityClass;
import org.apache.commons.lang3.StringUtils;
@UtilityClass
public class ValidationUtils {
public static final Pattern NAME_PATTERN =
Pattern.compile("^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$");
public static final String NAME_VALIDATION_MESSAGE = """
Super administrator username must be a valid subdomain name, the name must:
1. contain no more than 63 characters
2. contain only lowercase alphanumeric characters, '-' or '.'
3. start with an alphanumeric character
4. end with an alphanumeric character
""";
/**
* Validates the name.
*
* @param name name for validation
* @return true if the name is valid
*/
public static boolean validateName(String name) {
if (StringUtils.isBlank(name)) {
return false;
}
boolean matches = NAME_PATTERN.matcher(name).matches();
return matches && name.length() <= 63;
}
}

View File

@ -70,5 +70,7 @@ public class HaloProperties implements Validator {
errors.rejectValue("externalUrl", "external-url.required.when-using-absolute-permalink",
"External URL is required when property `use-absolute-permalink` is set to true.");
}
SecurityProperties.Initializer.validateUsername(props.getSecurity().getInitializer(),
errors);
}
}

View File

@ -3,8 +3,11 @@ package run.halo.app.infra.properties;
import static org.springframework.security.web.server.header.ReferrerPolicyServerHttpHeadersWriter.ReferrerPolicy.STRICT_ORIGIN_WHEN_CROSS_ORIGIN;
import lombok.Data;
import org.springframework.lang.NonNull;
import org.springframework.security.web.server.header.ReferrerPolicyServerHttpHeadersWriter.ReferrerPolicy;
import org.springframework.security.web.server.header.XFrameOptionsServerHttpHeadersWriter.Mode;
import org.springframework.validation.Errors;
import run.halo.app.infra.ValidationUtils;
@Data
public class SecurityProperties {
@ -39,6 +42,14 @@ public class SecurityProperties {
private String superAdminPassword;
static void validateUsername(@NonNull Initializer initializer, @NonNull Errors errors) {
if (initializer.isDisabled() || ValidationUtils.validateName(
initializer.getSuperAdminUsername())) {
return;
}
errors.rejectValue("security.initializer.superAdminUsername",
"initializer.superAdminUsername.invalid",
ValidationUtils.NAME_VALIDATION_MESSAGE);
}
}
}

View File

@ -0,0 +1,59 @@
package run.halo.app.infra;
import static org.assertj.core.api.Assertions.assertThat;
import org.apache.commons.lang3.StringUtils;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
/**
* Tests for {@link ValidationUtils}.
*
* @author guqing
* @since 2.5.0
*/
class ValidationUtilsTest {
@Nested
class NameValidationTest {
@Test
void nullName() {
assertThat(ValidationUtils.validateName(null)).isFalse();
}
@Test
void emptyUsername() {
assertThat(ValidationUtils.validateName("")).isFalse();
}
@Test
void startWithIllegalCharacter() {
assertThat(ValidationUtils.validateName("-abc")).isFalse();
}
@Test
void endWithIllegalCharacter() {
assertThat(ValidationUtils.validateName("abc-")).isFalse();
assertThat(ValidationUtils.validateName("abcD")).isFalse();
}
@Test
void middleWithIllegalCharacter() {
assertThat(ValidationUtils.validateName("ab?c")).isFalse();
}
@Test
void moreThan63Characters() {
assertThat(ValidationUtils.validateName(StringUtils.repeat('a', 64))).isFalse();
}
@Test
void correctUsername() {
assertThat(ValidationUtils.validateName("abc")).isTrue();
assertThat(ValidationUtils.validateName("ab-c")).isTrue();
assertThat(ValidationUtils.validateName("1st")).isTrue();
assertThat(ValidationUtils.validateName("ast1")).isTrue();
assertThat(ValidationUtils.validateName("ast-1")).isTrue();
}
}
}

View File

@ -59,5 +59,4 @@ class SuperAdminInitializerTest {
return false;
}));
}
}