Encapsulate extractPrincipalNameFromEmail property

This simplifies the logic when extracting the principal and allows
more flexibility in the future by allowing the format and regex to be
added as setters.
This commit is contained in:
Rob Winch 2025-06-10 11:41:56 -05:00
parent 5f2efbea6a
commit f690a7f3df

View File

@ -39,29 +39,31 @@ import org.springframework.util.Assert;
* format RFC1779 will be used: DN is extracted from EMAIlADDRESS. * format RFC1779 will be used: DN is extracted from EMAIlADDRESS.
* *
* @author Max Batischev * @author Max Batischev
* @author Rob Winch
* @since 7.0 * @since 7.0
*/ */
public final class SubjectX500PrincipalExtractor implements X509PrincipalExtractor, MessageSourceAware { public final class SubjectX500PrincipalExtractor implements X509PrincipalExtractor, MessageSourceAware {
private final Log logger = LogFactory.getLog(getClass()); private final Log logger = LogFactory.getLog(getClass());
private static final Pattern EMAIL_SUBJECT_DN_PATTERN = Pattern.compile("OID.1.2.840.113549.1.9.1=(.*?)(?:,|$)",
Pattern.CASE_INSENSITIVE);
private static final Pattern CN_SUBJECT_DN_PATTERN = Pattern.compile("CN=(.*?)(?:,|$)", Pattern.CASE_INSENSITIVE);
private MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); private MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
private boolean extractPrincipalNameFromEmail = false; private Pattern subjectDnPattern = CN_SUBJECT_DN_PATTERN;
private final Pattern cnSubjectDnPattern = Pattern.compile("CN=(.*?)(?:,|$)", Pattern.CASE_INSENSITIVE); private String x500PrincipalFormat = X500Principal.RFC2253;
private final Pattern emailSubjectDnPattern = Pattern.compile("OID.1.2.840.113549.1.9.1=(.*?)(?:,|$)",
Pattern.CASE_INSENSITIVE);
@Override @Override
public Object extractPrincipal(X509Certificate clientCert) { public Object extractPrincipal(X509Certificate clientCert) {
Assert.notNull(clientCert, "clientCert cannot be null"); Assert.notNull(clientCert, "clientCert cannot be null");
X500Principal principal = clientCert.getSubjectX500Principal(); X500Principal principal = clientCert.getSubjectX500Principal();
String subjectDN = this.extractPrincipalNameFromEmail ? principal.getName("RFC1779") : principal.getName(); String subjectDN = principal.getName(this.x500PrincipalFormat);
this.logger.debug(LogMessage.format("Subject DN is '%s'", subjectDN)); this.logger.debug(LogMessage.format("Subject DN is '%s'", subjectDN));
Matcher matcher = this.extractPrincipalNameFromEmail ? this.emailSubjectDnPattern.matcher(subjectDN) Matcher matcher = this.subjectDnPattern.matcher(subjectDN);
: this.cnSubjectDnPattern.matcher(subjectDN);
if (!matcher.find()) { if (!matcher.find()) {
throw new BadCredentialsException(this.messages.getMessage("SubjectX500PrincipalExtractor.noMatching", throw new BadCredentialsException(this.messages.getMessage("SubjectX500PrincipalExtractor.noMatching",
new Object[] { subjectDN }, "No matching pattern was found in subject DN: {0}")); new Object[] { subjectDN }, "No matching pattern was found in subject DN: {0}"));
@ -82,7 +84,14 @@ public final class SubjectX500PrincipalExtractor implements X509PrincipalExtract
* @param extractPrincipalNameFromEmail whether to extract DN from EMAIlADDRESS * @param extractPrincipalNameFromEmail whether to extract DN from EMAIlADDRESS
*/ */
public void setExtractPrincipalNameFromEmail(boolean extractPrincipalNameFromEmail) { public void setExtractPrincipalNameFromEmail(boolean extractPrincipalNameFromEmail) {
this.extractPrincipalNameFromEmail = extractPrincipalNameFromEmail; if (extractPrincipalNameFromEmail) {
this.subjectDnPattern = EMAIL_SUBJECT_DN_PATTERN;
this.x500PrincipalFormat = X500Principal.RFC1779;
}
else {
this.subjectDnPattern = CN_SUBJECT_DN_PATTERN;
this.x500PrincipalFormat = X500Principal.RFC2253;
}
} }
} }