Browse Source

Add relying-party-registrations#id

Closes gh-14487
Josh Cummings 1 năm trước cách đây
mục cha
commit
a4dbf458ab

+ 7 - 2
config/src/main/java/org/springframework/security/config/saml2/RelyingPartyRegistrationsBeanDefinitionParser.java

@@ -64,6 +64,8 @@ public final class RelyingPartyRegistrationsBeanDefinitionParser implements Bean
 
 	private static final String ELT_ENCRYPTION_CREDENTIAL = "encryption-credential";
 
+	private static final String ATT_ID = "id";
+
 	private static final String ATT_REGISTRATION_ID = "registration-id";
 
 	private static final String ATT_ASSERTING_PARTY_ID = "asserting-party-id";
@@ -108,8 +110,11 @@ public final class RelyingPartyRegistrationsBeanDefinitionParser implements Bean
 			.rootBeanDefinition(InMemoryRelyingPartyRegistrationRepository.class)
 			.addConstructorArgValue(relyingPartyRegistrations)
 			.getBeanDefinition();
-		String relyingPartyRegistrationRepositoryId = parserContext.getReaderContext()
-			.generateBeanName(relyingPartyRegistrationRepositoryBean);
+		String relyingPartyRegistrationRepositoryId = element.getAttribute(ATT_ID);
+		if (!StringUtils.hasText(relyingPartyRegistrationRepositoryId)) {
+			relyingPartyRegistrationRepositoryId = parserContext.getReaderContext()
+				.generateBeanName(relyingPartyRegistrationRepositoryBean);
+		}
 		parserContext.registerBeanComponent(new BeanComponentDefinition(relyingPartyRegistrationRepositoryBean,
 				relyingPartyRegistrationRepositoryId));
 		parserContext.popAndRegisterContainingComponent();

+ 4 - 1
config/src/main/resources/org/springframework/security/config/spring-security-6.3.rnc

@@ -744,7 +744,10 @@ saml2-logout.attlist &=
 
 relying-party-registrations =
 	## Container element for relying party(ies) registered with a SAML 2.0 identity provider
-	element relying-party-registrations {relying-party-registration+, asserting-party*}
+	element relying-party-registrations {relying-party-registrations.attlist, relying-party-registration+, asserting-party*}
+relying-party-registrations.attlist &=
+    ## The identifier by which to refer to the repository in other beans
+    attribute id {xsd:token}?
 
 relying-party-registration =
 	## Represents a relying party registered with a SAML 2.0 identity provider

+ 9 - 0
config/src/main/resources/org/springframework/security/config/spring-security-6.3.xsd

@@ -2188,8 +2188,17 @@
             <xs:element maxOccurs="unbounded" ref="security:relying-party-registration"/>
             <xs:element minOccurs="0" maxOccurs="unbounded" ref="security:asserting-party"/>
          </xs:sequence>
+         <xs:attributeGroup ref="security:relying-party-registrations.attlist"/>
       </xs:complexType>
    </xs:element>
+  <xs:attributeGroup name="relying-party-registrations.attlist">
+      <xs:attribute name="id" type="xs:token">
+         <xs:annotation>
+            <xs:documentation>The identifier by which to refer to the repository in other beans
+                </xs:documentation>
+         </xs:annotation>
+      </xs:attribute>
+  </xs:attributeGroup>
   <xs:element name="relying-party-registration">
       <xs:annotation>
          <xs:documentation>Represents a relying party registered with a SAML 2.0 identity provider

+ 20 - 0
config/src/test/java/org/springframework/security/config/saml2/RelyingPartyRegistrationsBeanDefinitionParserTests.java

@@ -16,6 +16,7 @@
 
 package org.springframework.security.config.saml2;
 
+import jakarta.servlet.http.HttpServletRequest;
 import okhttp3.mockwebserver.MockResponse;
 import okhttp3.mockwebserver.MockWebServer;
 import org.junit.jupiter.api.AfterEach;
@@ -23,16 +24,21 @@ import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.core.convert.converter.Converter;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.MediaType;
+import org.springframework.mock.web.MockHttpServletRequest;
 import org.springframework.security.config.test.SpringTestContext;
 import org.springframework.security.config.test.SpringTestContextExtension;
 import org.springframework.security.saml2.provider.service.registration.InMemoryRelyingPartyRegistrationRepository;
 import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
 import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository;
 import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding;
+import org.springframework.security.saml2.provider.service.web.authentication.OpenSaml4AuthenticationRequestResolver;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.verify;
 
 /**
  * Tests for {@link RelyingPartyRegistrationsBeanDefinitionParser}.
@@ -118,6 +124,7 @@ public class RelyingPartyRegistrationsBeanDefinitionParserTests {
 	// @formatter:on
 
 	@Autowired
+	@Qualifier("registrations")
 	private RelyingPartyRegistrationRepository relyingPartyRegistrationRepository;
 
 	public final SpringTestContext spring = new SpringTestContext(this);
@@ -268,6 +275,19 @@ public class RelyingPartyRegistrationsBeanDefinitionParserTests {
 				"http://www.w3.org/2001/04/xmldsig-more#rsa-sha384");
 	}
 
+	@Test
+	public void parseWhenRelayStateResolverThenUses() {
+		this.spring.configLocations(xml("RelayStateResolver")).autowire();
+		Converter<HttpServletRequest, String> relayStateResolver = this.spring.getContext().getBean(Converter.class);
+		OpenSaml4AuthenticationRequestResolver authenticationRequestResolver = this.spring.getContext()
+			.getBean(OpenSaml4AuthenticationRequestResolver.class);
+		MockHttpServletRequest request = new MockHttpServletRequest();
+		request.setRequestURI("/saml2/authenticate/one");
+		request.setServletPath("/saml2/authenticate/one");
+		authenticationRequestResolver.resolve(request);
+		verify(relayStateResolver).convert(request);
+	}
+
 	private static MockResponse xmlResponse(String xml) {
 		return new MockResponse().setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE).setBody(xml);
 	}

+ 5 - 5
config/src/test/resources/org/springframework/security/config/saml2/RelyingPartyRegistrationsBeanDefinitionParserTests-MultiRegistration.xml

@@ -23,20 +23,20 @@
 			https://www.springframework.org/schema/security/spring-security.xsd
 			http://www.springframework.org/schema/beans
 			https://www.springframework.org/schema/beans/spring-beans.xsd">
-  
-  <relying-party-registrations>
+
+  <relying-party-registrations id="registrations">
     <relying-party-registration registration-id="one"
                                 entity-id="{baseUrl}/saml2/service-provider-metadata/{registrationId}"
                                 assertion-consumer-service-location="{baseUrl}/login/saml2/sso/{registrationId}"
                                 assertion-consumer-service-binding="REDIRECT"
                                 asserting-party-id="google"/>
-    
+
     <relying-party-registration registration-id="two"
                                 entity-id="{baseUrl}/saml2/service-provider-metadata/{registrationId}"
                                 assertion-consumer-service-location="{baseUrl}/login/saml2/sso/{registrationId}"
                                 assertion-consumer-service-binding="POST"
                                 asserting-party-id="simple-saml"/>
-    
+
     <asserting-party asserting-party-id="google" entity-id="https://accounts.google.com/o/saml2/idp/entity-id"
                      want-authn-requests-signed="true"
                      single-sign-on-service-location="https://accounts.google.com/o/saml2/idp/sso-url"
@@ -48,7 +48,7 @@
           certificate-location="classpath:org/springframework/security/config/saml2/idp-certificate.crt"
           private-key-location="classpath:org/springframework/security/config/saml2/rp-private.key"/>
     </asserting-party>
-    
+
     <asserting-party asserting-party-id="simple-saml"
                      entity-id="https://simplesaml-for-spring-saml.apps.pcfone.io/saml2/idp/metadata.php"
                      single-sign-on-service-location="https://simplesaml-for-spring-saml.apps.pcfone.io/saml2/idp/SSOService.php"

+ 58 - 0
config/src/test/resources/org/springframework/security/config/saml2/RelyingPartyRegistrationsBeanDefinitionParserTests-RelayStateResolver.xml

@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2021 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: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">
+
+  <relying-party-registrations id="registrations">
+    <relying-party-registration registration-id="one"
+                                entity-id="{baseUrl}/saml2/service-provider-metadata/{registrationId}"
+                                assertion-consumer-service-location="{baseUrl}/login/saml2/sso/{registrationId}"
+                                assertion-consumer-service-binding="REDIRECT"
+                                asserting-party-id="google">
+      <signing-credential
+          certificate-location="classpath:org/springframework/security/config/saml2/rp-certificate.crt"
+          private-key-location="classpath:org/springframework/security/config/saml2/rp-private.key"/>
+	</relying-party-registration>
+    <asserting-party asserting-party-id="google" entity-id="https://accounts.google.com/o/saml2/idp/entity-id"
+                     want-authn-requests-signed="true"
+                     single-sign-on-service-location="https://accounts.google.com/o/saml2/idp/sso-url"
+                     single-sign-on-service-binding="POST">
+      <verification-credential
+          certificate-location="classpath:org/springframework/security/config/saml2/idp-certificate.crt"
+          private-key-location="classpath:org/springframework/security/config/saml2/rp-private.key"/>
+      <encryption-credential
+          certificate-location="classpath:org/springframework/security/config/saml2/idp-certificate.crt"
+          private-key-location="classpath:org/springframework/security/config/saml2/rp-private.key"/>
+    </asserting-party>
+  </relying-party-registrations>
+
+  <b:bean class="org.springframework.security.saml2.provider.service.web.authentication.OpenSaml4AuthenticationRequestResolver">
+    <b:constructor-arg ref="registrations"/>
+    <b:property name="relayStateResolver" ref="relayStateResolver"/>
+  </b:bean>
+
+  <b:bean name="relayStateResolver" class="org.mockito.Mockito" factory-method="mock">
+    <b:constructor-arg value="org.springframework.core.convert.converter.Converter" type="java.lang.Class"/>
+  </b:bean>
+</b:beans>

+ 3 - 3
config/src/test/resources/org/springframework/security/config/saml2/RelyingPartyRegistrationsBeanDefinitionParserTests-SingleRegistration.xml

@@ -23,14 +23,14 @@
 			https://www.springframework.org/schema/security/spring-security.xsd
 			http://www.springframework.org/schema/beans
 			https://www.springframework.org/schema/beans/spring-beans.xsd">
-  
-  <relying-party-registrations>
+
+  <relying-party-registrations id="registrations">
     <relying-party-registration registration-id="one"
                                 entity-id="{baseUrl}/saml2/service-provider-metadata/{registrationId}"
                                 assertion-consumer-service-location="{baseUrl}/login/saml2/sso/{registrationId}"
                                 assertion-consumer-service-binding="REDIRECT"
                                 asserting-party-id="google"/>
-    
+
     <asserting-party asserting-party-id="google" entity-id="https://accounts.google.com/o/saml2/idp/entity-id"
                      want-authn-requests-signed="true"
                      single-sign-on-service-location="https://accounts.google.com/o/saml2/idp/sso-url"

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

@@ -1331,6 +1331,12 @@ Reference to an `OpaqueTokenAuthenticationConverter`. Responsible for converting
 == <relying-party-registrations>
 The container element for relying party(ies) registered (xref:servlet/saml2/login/overview.adoc#servlet-saml2login-relyingpartyregistration[ClientRegistration]) with a SAML 2.0 Identity Provider.
 
+[[nsa-relying-party-registrations-attributes]]
+=== <relying-party-registrations> Attributes
+
+[[nsa-relying-party-registrations-id]]
+* **id**
+The ID that uniquely identifies the `RelyingPartyRegistrationRepository`.
 
 [[nsa-relying-party-registrations-children]]
 === Child Elements of <relying-party-registrations>