Skip to content

Commit 7bf2730

Browse files
committed
Add x509@principal-extractor-ref
Enables customizing the X500PrincipalExtractor
1 parent 88ed4a5 commit 7bf2730

File tree

7 files changed

+133
-3
lines changed

7 files changed

+133
-3
lines changed

config/src/main/java/org/springframework/security/config/http/AuthenticationConfigBuilder.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -521,11 +521,23 @@ void createX509Filter(BeanReference authManager,
521521
filterBuilder.addPropertyValue("authenticationManager", authManager);
522522
filterBuilder.addPropertyValue("securityContextHolderStrategy",
523523
authenticationFilterSecurityContextHolderStrategyRef);
524-
String regex = x509Elt.getAttribute("subject-principal-regex");
525-
if (StringUtils.hasText(regex)) {
524+
String principalExtractorRef = x509Elt.getAttribute("principal-extractor-ref");
525+
String subjectPrincipalRegex = x509Elt.getAttribute("subject-principal-regex");
526+
boolean hasPrincipalExtractorRef = StringUtils.hasText(principalExtractorRef);
527+
boolean hasSubjectPrincipalRegex = StringUtils.hasText(subjectPrincipalRegex);
528+
if (hasPrincipalExtractorRef && hasSubjectPrincipalRegex) {
529+
this.pc.getReaderContext()
530+
.error("The attribute 'principal-extractor-ref' cannot be used together with the 'subject-principal-regex' attribute within <"
531+
+ Elements.X509 + ">", this.pc.extractSource(x509Elt));
532+
}
533+
if (hasPrincipalExtractorRef) {
534+
RuntimeBeanReference principalExtractor = new RuntimeBeanReference(principalExtractorRef);
535+
filterBuilder.addPropertyValue("principalExtractor", principalExtractor);
536+
}
537+
if (hasSubjectPrincipalRegex) {
526538
BeanDefinitionBuilder extractor = BeanDefinitionBuilder
527539
.rootBeanDefinition(SubjectDnX509PrincipalExtractor.class);
528-
extractor.addPropertyValue("subjectDnRegex", regex);
540+
extractor.addPropertyValue("subjectDnRegex", subjectPrincipalRegex);
529541
filterBuilder.addPropertyValue("principalExtractor", extractor.getBeanDefinition());
530542
}
531543
injectAuthenticationDetailsSource(x509Elt, filterBuilder);

config/src/main/resources/org/springframework/security/config/spring-security-7.0.rnc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,6 +1053,9 @@ x509.attlist &=
10531053
x509.attlist &=
10541054
## Reference to an AuthenticationDetailsSource which will be used by the authentication filter
10551055
attribute authentication-details-source-ref {xsd:token}?
1056+
x509.attlist &=
1057+
## Reference to an X509PrincipalExtractor which will be used by the authentication filter
1058+
attribute principal-extractor-ref {xsd:token}?
10561059

10571060
jee =
10581061
## Adds a J2eePreAuthenticatedProcessingFilter to the filter chain to provide integration with container authentication.

config/src/main/resources/org/springframework/security/config/spring-security-7.0.xsd

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2917,6 +2917,12 @@
29172917
</xs:documentation>
29182918
</xs:annotation>
29192919
</xs:attribute>
2920+
<xs:attribute name="principal-extractor-ref" type="xs:token">
2921+
<xs:annotation>
2922+
<xs:documentation>Reference to an X509PrincipalExtractor which will be used by the authentication filter
2923+
</xs:documentation>
2924+
</xs:annotation>
2925+
</xs:attribute>
29202926
</xs:attributeGroup>
29212927
<xs:element name="jee">
29222928
<xs:annotation>

config/src/test/java/org/springframework/security/config/http/MiscHttpConfigTests.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.io.OutputStream;
2222
import java.security.AccessController;
2323
import java.security.Principal;
24+
import java.security.cert.X509Certificate;
2425
import java.util.Arrays;
2526
import java.util.Collection;
2627
import java.util.HashSet;
@@ -91,6 +92,7 @@
9192
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
9293
import org.springframework.security.web.authentication.logout.LogoutFilter;
9394
import org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter;
95+
import org.springframework.security.web.authentication.preauth.x509.X509TestUtils;
9496
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
9597
import org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter;
9698
import org.springframework.security.web.authentication.ui.DefaultResourcesFilter;
@@ -398,6 +400,27 @@ public void configureWhenUsingX509ThenAddsX509FilterCorrectly() {
398400
.containsSubsequence(CsrfFilter.class, X509AuthenticationFilter.class, ExceptionTranslationFilter.class);
399401
}
400402

403+
@Test
404+
public void getWhenUsingX509PrincipalExtractorRef() throws Exception {
405+
this.spring.configLocations(xml("X509PrincipalExtractorRef")).autowire();
406+
X509Certificate certificate = X509TestUtils.buildTestCertificate();
407+
RequestPostProcessor x509 = x509(certificate);
408+
// @formatter:off
409+
this.mvc.perform(get("/protected").with(x509))
410+
.andExpect(status().isOk());
411+
// @formatter:on
412+
}
413+
414+
@Test
415+
public void getWhenUsingX509PrincipalExtractorRefAndSubjectPrincipalRegex() throws Exception {
416+
String xmlResourceName = "X509PrincipalExtractorRefAndSubjectPrincipalRegex";
417+
// @formatter:off
418+
assertThatExceptionOfType(BeanDefinitionParsingException.class)
419+
.isThrownBy(() -> this.spring.configLocations(xml(xmlResourceName)).autowire())
420+
.withMessage("Configuration problem: The attribute 'principal-extractor-ref' cannot be used together with the 'subject-principal-regex' attribute within <x509>\n" + "Offending resource: class path resource [org/springframework/security/config/http/MiscHttpConfigTests-X509PrincipalExtractorRefAndSubjectPrincipalRegex.xml]");
421+
// @formatter:on
422+
}
423+
401424
@Test
402425
public void getWhenUsingX509AndPropertyPlaceholderThenSubjectPrincipalRegexIsConfigured() throws Exception {
403426
System.setProperty("subject_principal_regex", "OU=(.*?)(?:,|$)");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
~ Copyright 2002-2018 the original author or authors.
4+
~
5+
~ Licensed under the Apache License, Version 2.0 (the "License");
6+
~ you may not use this file except in compliance with the License.
7+
~ You may obtain a copy of the License at
8+
~
9+
~ https://www.apache.org/licenses/LICENSE-2.0
10+
~
11+
~ Unless required by applicable law or agreed to in writing, software
12+
~ distributed under the License is distributed on an "AS IS" BASIS,
13+
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
~ See the License for the specific language governing permissions and
15+
~ limitations under the License.
16+
-->
17+
18+
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
19+
xmlns:p="http://www.springframework.org/schema/p"
20+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
21+
xmlns="http://www.springframework.org/schema/security"
22+
xsi:schemaLocation="
23+
http://www.springframework.org/schema/security
24+
https://www.springframework.org/schema/security/spring-security.xsd
25+
http://www.springframework.org/schema/beans
26+
https://www.springframework.org/schema/beans/spring-beans.xsd">
27+
28+
<http>
29+
<x509 principal-extractor-ref="principalExtractor"/>
30+
<intercept-url pattern="/**" access="authenticated"/>
31+
</http>
32+
33+
<user-service id="us">
34+
<user name="luke@monkeymachine" password="{noop}password" authorities="ROLE_USER"/>
35+
</user-service>
36+
37+
<b:bean name="principalExtractor" class="org.springframework.security.web.authentication.preauth.x509.SubjectX500PrincipalExtractor"
38+
p:extractPrincipalNameFromEmail="true"/>
39+
40+
<b:import resource="MiscHttpConfigTests-controllers.xml"/>
41+
</b:beans>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
~ Copyright 2002-2018 the original author or authors.
4+
~
5+
~ Licensed under the Apache License, Version 2.0 (the "License");
6+
~ you may not use this file except in compliance with the License.
7+
~ You may obtain a copy of the License at
8+
~
9+
~ https://www.apache.org/licenses/LICENSE-2.0
10+
~
11+
~ Unless required by applicable law or agreed to in writing, software
12+
~ distributed under the License is distributed on an "AS IS" BASIS,
13+
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
~ See the License for the specific language governing permissions and
15+
~ limitations under the License.
16+
-->
17+
18+
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
19+
xmlns:p="http://www.springframework.org/schema/p"
20+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
21+
xmlns="http://www.springframework.org/schema/security"
22+
xsi:schemaLocation="
23+
http://www.springframework.org/schema/security
24+
https://www.springframework.org/schema/security/spring-security.xsd
25+
http://www.springframework.org/schema/beans
26+
https://www.springframework.org/schema/beans/spring-beans.xsd">
27+
28+
<http>
29+
<x509 principal-extractor-ref="principalExtractor" subject-principal-regex="(.*)"/>
30+
<intercept-url pattern="/**" access="authenticated"/>
31+
</http>
32+
33+
<user-service id="us">
34+
<user name="luke@monkeymachine" password="{noop}password" authorities="ROLE_USER"/>
35+
</user-service>
36+
37+
<b:bean name="principalExtractor" class="org.springframework.security.web.authentication.preauth.x509.SubjectX500PrincipalExtractor"
38+
p:extractPrincipalNameFromEmail="true"/>
39+
40+
<b:import resource="MiscHttpConfigTests-controllers.xml"/>
41+
</b:beans>

docs/modules/ROOT/pages/servlet/appendix/namespace/http.adoc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2218,6 +2218,10 @@ A `PreAuthenticatedAuthenticationProvider` will also be created which delegates
22182218
* **authentication-details-source-ref**
22192219
A reference to an `AuthenticationDetailsSource`
22202220

2221+
[[nsa-x509-principal-extractor-ref]]
2222+
* **principal-extractor-ref**
2223+
Reference to an `X509PrincipalExtractor` which will be used by the authentication filter.
2224+
22212225

22222226
[[nsa-x509-subject-principal-regex]]
22232227
* **subject-principal-regex**

0 commit comments

Comments
 (0)