Add setMetadataFilename method to Saml2MetadataFilter
Closes gh-9317
This commit is contained in:
parent
857830f695
commit
fb391c5dcd
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2020 the original author or authors.
|
* Copyright 2002-2021 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -42,10 +42,14 @@ import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
*/
|
*/
|
||||||
public final class Saml2MetadataFilter extends OncePerRequestFilter {
|
public final class Saml2MetadataFilter extends OncePerRequestFilter {
|
||||||
|
|
||||||
|
public static final String DEFAULT_METADATA_FILE_NAME = "saml-{registrationId}-metadata.xml";
|
||||||
|
|
||||||
private final Converter<HttpServletRequest, RelyingPartyRegistration> relyingPartyRegistrationConverter;
|
private final Converter<HttpServletRequest, RelyingPartyRegistration> relyingPartyRegistrationConverter;
|
||||||
|
|
||||||
private final Saml2MetadataResolver saml2MetadataResolver;
|
private final Saml2MetadataResolver saml2MetadataResolver;
|
||||||
|
|
||||||
|
private String metadataFilename = DEFAULT_METADATA_FILE_NAME;
|
||||||
|
|
||||||
private RequestMatcher requestMatcher = new AntPathRequestMatcher(
|
private RequestMatcher requestMatcher = new AntPathRequestMatcher(
|
||||||
"/saml2/service-provider-metadata/{registrationId}");
|
"/saml2/service-provider-metadata/{registrationId}");
|
||||||
|
|
||||||
|
@ -78,8 +82,9 @@ public final class Saml2MetadataFilter extends OncePerRequestFilter {
|
||||||
private void writeMetadataToResponse(HttpServletResponse response, String registrationId, String metadata)
|
private void writeMetadataToResponse(HttpServletResponse response, String registrationId, String metadata)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
response.setContentType(MediaType.APPLICATION_XML_VALUE);
|
response.setContentType(MediaType.APPLICATION_XML_VALUE);
|
||||||
response.setHeader(HttpHeaders.CONTENT_DISPOSITION,
|
String fileName = this.metadataFilename.replace("{registrationId}", registrationId);
|
||||||
"attachment; filename=\"saml-" + registrationId + "-metadata.xml\"");
|
String format = "attachment; filename=\"%s\"";
|
||||||
|
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, String.format(format, fileName));
|
||||||
response.setContentLength(metadata.length());
|
response.setContentLength(metadata.length());
|
||||||
response.getWriter().write(metadata);
|
response.getWriter().write(metadata);
|
||||||
}
|
}
|
||||||
|
@ -94,4 +99,20 @@ public final class Saml2MetadataFilter extends OncePerRequestFilter {
|
||||||
this.requestMatcher = requestMatcher;
|
this.requestMatcher = requestMatcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the metadata filename template containing the {@code {registrationId}}
|
||||||
|
* template variable.
|
||||||
|
*
|
||||||
|
* <br />
|
||||||
|
* The default value is {@code saml-{registrationId}-metadata.xml}
|
||||||
|
* @param metadataFilename metadata filename, must contain a {registrationId}
|
||||||
|
* @since 5.5
|
||||||
|
*/
|
||||||
|
public void setMetadataFilename(String metadataFilename) {
|
||||||
|
Assert.hasText(metadataFilename, "metadataFilename cannot be empty");
|
||||||
|
Assert.isTrue(metadataFilename.contains("{registrationId}"),
|
||||||
|
"metadataFilename must contain a {registrationId} match variable");
|
||||||
|
this.metadataFilename = metadataFilename;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2020 the original author or authors.
|
* Copyright 2002-2021 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,11 +16,15 @@
|
||||||
|
|
||||||
package org.springframework.security.saml2.provider.service.web;
|
package org.springframework.security.saml2.provider.service.web;
|
||||||
|
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
import javax.servlet.FilterChain;
|
import javax.servlet.FilterChain;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.mock.web.MockHttpServletRequest;
|
import org.springframework.mock.web.MockHttpServletRequest;
|
||||||
import org.springframework.mock.web.MockHttpServletResponse;
|
import org.springframework.mock.web.MockHttpServletResponse;
|
||||||
import org.springframework.security.saml2.core.TestSaml2X509Credentials;
|
import org.springframework.security.saml2.core.TestSaml2X509Credentials;
|
||||||
|
@ -31,6 +35,7 @@ import org.springframework.security.saml2.provider.service.registration.TestRely
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||||
import static org.mockito.BDDMockito.given;
|
import static org.mockito.BDDMockito.given;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
@ -120,4 +125,43 @@ public class Saml2MetadataFilterTests {
|
||||||
assertThatIllegalArgumentException().isThrownBy(() -> this.filter.setRequestMatcher(null));
|
assertThatIllegalArgumentException().isThrownBy(() -> this.filter.setRequestMatcher(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setMetadataFilenameWhenEmptyThenThrowsException() {
|
||||||
|
assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> this.filter.setMetadataFilename(" "))
|
||||||
|
.withMessage("metadataFilename cannot be empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setMetadataFilenameWhenMissingRegistrationIdVariableThenThrowsException() {
|
||||||
|
assertThatExceptionOfType(IllegalArgumentException.class)
|
||||||
|
.isThrownBy(() -> this.filter.setMetadataFilename("metadata-filename.xml"))
|
||||||
|
.withMessage("metadataFilename must contain a {registrationId} match variable");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void doFilterWhenSetMetadataFilenameThenUses() throws Exception {
|
||||||
|
String testMetadataFilename = "test-{registrationId}-metadata.xml";
|
||||||
|
this.request.setPathInfo("/saml2/service-provider-metadata/validRegistration");
|
||||||
|
RelyingPartyRegistration validRegistration = TestRelyingPartyRegistrations.noCredentials()
|
||||||
|
.assertingPartyDetails((party) -> party.verificationX509Credentials(
|
||||||
|
(c) -> c.add(TestSaml2X509Credentials.relyingPartyVerifyingCredential())))
|
||||||
|
.build();
|
||||||
|
String generatedMetadata = "<xml>test</xml>";
|
||||||
|
given(this.resolver.resolve(validRegistration)).willReturn(generatedMetadata);
|
||||||
|
|
||||||
|
this.filter = new Saml2MetadataFilter((request) -> validRegistration, this.resolver);
|
||||||
|
this.filter.setMetadataFilename(testMetadataFilename);
|
||||||
|
this.filter.doFilter(this.request, this.response, this.chain);
|
||||||
|
|
||||||
|
verifyNoInteractions(this.chain);
|
||||||
|
assertThat(this.response.getStatus()).isEqualTo(200);
|
||||||
|
assertThat(this.response.getContentAsString()).isEqualTo(generatedMetadata);
|
||||||
|
|
||||||
|
String fileName = testMetadataFilename.replace("{registrationId}", validRegistration.getRegistrationId());
|
||||||
|
String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.name());
|
||||||
|
assertThat(this.response.getHeaderValue(HttpHeaders.CONTENT_DISPOSITION)).asString()
|
||||||
|
.isEqualTo("attachment; filename=\"%s\"; filename*=UTF-8''%s", fileName, encodedFileName);
|
||||||
|
verify(this.resolver).resolve(validRegistration);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue