瀏覽代碼

Add x509@principal-extractor-ref

Enables customizing the X500PrincipalExtractor
Rob Winch 2 月之前
父節點
當前提交
7bf2730a53

+ 15 - 3
config/src/main/java/org/springframework/security/config/http/AuthenticationConfigBuilder.java

@@ -521,11 +521,23 @@ final class AuthenticationConfigBuilder {
 			filterBuilder.addPropertyValue("authenticationManager", authManager);
 			filterBuilder.addPropertyValue("securityContextHolderStrategy",
 					authenticationFilterSecurityContextHolderStrategyRef);
-			String regex = x509Elt.getAttribute("subject-principal-regex");
-			if (StringUtils.hasText(regex)) {
+			String principalExtractorRef = x509Elt.getAttribute("principal-extractor-ref");
+			String subjectPrincipalRegex = x509Elt.getAttribute("subject-principal-regex");
+			boolean hasPrincipalExtractorRef = StringUtils.hasText(principalExtractorRef);
+			boolean hasSubjectPrincipalRegex = StringUtils.hasText(subjectPrincipalRegex);
+			if (hasPrincipalExtractorRef && hasSubjectPrincipalRegex) {
+				this.pc.getReaderContext()
+					.error("The attribute 'principal-extractor-ref' cannot be used together with the 'subject-principal-regex' attribute within <"
+							+ Elements.X509 + ">", this.pc.extractSource(x509Elt));
+			}
+			if (hasPrincipalExtractorRef) {
+				RuntimeBeanReference principalExtractor = new RuntimeBeanReference(principalExtractorRef);
+				filterBuilder.addPropertyValue("principalExtractor", principalExtractor);
+			}
+			if (hasSubjectPrincipalRegex) {
 				BeanDefinitionBuilder extractor = BeanDefinitionBuilder
 					.rootBeanDefinition(SubjectDnX509PrincipalExtractor.class);
-				extractor.addPropertyValue("subjectDnRegex", regex);
+				extractor.addPropertyValue("subjectDnRegex", subjectPrincipalRegex);
 				filterBuilder.addPropertyValue("principalExtractor", extractor.getBeanDefinition());
 			}
 			injectAuthenticationDetailsSource(x509Elt, filterBuilder);

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

@@ -1053,6 +1053,9 @@ x509.attlist &=
 x509.attlist &=
 	## Reference to an AuthenticationDetailsSource which will be used by the authentication filter
 	attribute authentication-details-source-ref {xsd:token}?
+x509.attlist &=
+	## Reference to an X509PrincipalExtractor which will be used by the authentication filter
+	attribute principal-extractor-ref {xsd:token}?
 
 jee =
 	## Adds a J2eePreAuthenticatedProcessingFilter to the filter chain to provide integration with container authentication.

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

@@ -2917,6 +2917,12 @@
                 </xs:documentation>
          </xs:annotation>
       </xs:attribute>
+      <xs:attribute name="principal-extractor-ref" type="xs:token">
+         <xs:annotation>
+            <xs:documentation>Reference to an X509PrincipalExtractor which will be used by the authentication filter
+                </xs:documentation>
+         </xs:annotation>
+      </xs:attribute>
   </xs:attributeGroup>
   <xs:element name="jee">
       <xs:annotation>

+ 23 - 0
config/src/test/java/org/springframework/security/config/http/MiscHttpConfigTests.java

@@ -21,6 +21,7 @@ import java.io.IOException;
 import java.io.OutputStream;
 import java.security.AccessController;
 import java.security.Principal;
+import java.security.cert.X509Certificate;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashSet;
@@ -91,6 +92,7 @@ import org.springframework.security.web.authentication.AnonymousAuthenticationFi
 import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
 import org.springframework.security.web.authentication.logout.LogoutFilter;
 import org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter;
+import org.springframework.security.web.authentication.preauth.x509.X509TestUtils;
 import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
 import org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter;
 import org.springframework.security.web.authentication.ui.DefaultResourcesFilter;
@@ -398,6 +400,27 @@ public class MiscHttpConfigTests {
 			.containsSubsequence(CsrfFilter.class, X509AuthenticationFilter.class, ExceptionTranslationFilter.class);
 	}
 
+	@Test
+	public void getWhenUsingX509PrincipalExtractorRef() throws Exception {
+		this.spring.configLocations(xml("X509PrincipalExtractorRef")).autowire();
+		X509Certificate certificate = X509TestUtils.buildTestCertificate();
+		RequestPostProcessor x509 = x509(certificate);
+		// @formatter:off
+		this.mvc.perform(get("/protected").with(x509))
+				.andExpect(status().isOk());
+		// @formatter:on
+	}
+
+	@Test
+	public void getWhenUsingX509PrincipalExtractorRefAndSubjectPrincipalRegex() throws Exception {
+		String xmlResourceName = "X509PrincipalExtractorRefAndSubjectPrincipalRegex";
+		// @formatter:off
+		assertThatExceptionOfType(BeanDefinitionParsingException.class)
+			.isThrownBy(() -> this.spring.configLocations(xml(xmlResourceName)).autowire())
+			.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]");
+		// @formatter:on
+	}
+
 	@Test
 	public void getWhenUsingX509AndPropertyPlaceholderThenSubjectPrincipalRegexIsConfigured() throws Exception {
 		System.setProperty("subject_principal_regex", "OU=(.*?)(?:,|$)");

+ 41 - 0
config/src/test/resources/org/springframework/security/config/http/MiscHttpConfigTests-X509PrincipalExtractorRef.xml

@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 the original author or authors.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~       https://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		 xmlns:p="http://www.springframework.org/schema/p"
+		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		xmlns="http://www.springframework.org/schema/security"
+		xsi:schemaLocation="
+			http://www.springframework.org/schema/security
+			https://www.springframework.org/schema/security/spring-security.xsd
+			http://www.springframework.org/schema/beans
+			https://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<http>
+		<x509 principal-extractor-ref="principalExtractor"/>
+		<intercept-url pattern="/**" access="authenticated"/>
+	</http>
+
+	<user-service id="us">
+		<user name="luke@monkeymachine" password="{noop}password" authorities="ROLE_USER"/>
+	</user-service>
+
+	<b:bean name="principalExtractor" class="org.springframework.security.web.authentication.preauth.x509.SubjectX500PrincipalExtractor"
+		p:extractPrincipalNameFromEmail="true"/>
+
+	<b:import resource="MiscHttpConfigTests-controllers.xml"/>
+</b:beans>

+ 41 - 0
config/src/test/resources/org/springframework/security/config/http/MiscHttpConfigTests-X509PrincipalExtractorRefAndSubjectPrincipalRegex.xml

@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 the original author or authors.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~       https://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		 xmlns:p="http://www.springframework.org/schema/p"
+		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		xmlns="http://www.springframework.org/schema/security"
+		xsi:schemaLocation="
+			http://www.springframework.org/schema/security
+			https://www.springframework.org/schema/security/spring-security.xsd
+			http://www.springframework.org/schema/beans
+			https://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<http>
+		<x509 principal-extractor-ref="principalExtractor" subject-principal-regex="(.*)"/>
+		<intercept-url pattern="/**" access="authenticated"/>
+	</http>
+
+	<user-service id="us">
+		<user name="luke@monkeymachine" password="{noop}password" authorities="ROLE_USER"/>
+	</user-service>
+
+	<b:bean name="principalExtractor" class="org.springframework.security.web.authentication.preauth.x509.SubjectX500PrincipalExtractor"
+		p:extractPrincipalNameFromEmail="true"/>
+
+	<b:import resource="MiscHttpConfigTests-controllers.xml"/>
+</b:beans>

+ 4 - 0
docs/modules/ROOT/pages/servlet/appendix/namespace/http.adoc

@@ -2218,6 +2218,10 @@ A `PreAuthenticatedAuthenticationProvider` will also be created which delegates
 * **authentication-details-source-ref**
 A reference to an `AuthenticationDetailsSource`
 
+[[nsa-x509-principal-extractor-ref]]
+* **principal-extractor-ref**
+Reference to an `X509PrincipalExtractor` which will be used by the authentication filter.
+
 
 [[nsa-x509-subject-principal-regex]]
 * **subject-principal-regex**