mirror of
				https://github.com/spring-projects/spring-security.git
				synced 2025-10-30 22:28:46 +00:00 
			
		
		
		
	Allow configuration of x509 through nested builder
Issue: gh-5557
This commit is contained in:
		
							parent
							
								
									bfc9538da1
								
							
						
					
					
						commit
						ae9eb6f56b
					
				| @ -861,6 +861,42 @@ public final class HttpSecurity extends | ||||
| 		return getOrApply(new X509Configurer<>()); | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Configures X509 based pre authentication. | ||||
| 	 * | ||||
| 	 * <h2>Example Configuration</h2> | ||||
| 	 * | ||||
| 	 * The following configuration will attempt to extract the username from the X509 | ||||
| 	 * certificate. Remember that the Servlet Container will need to be configured to | ||||
| 	 * request client certificates in order for this to work. | ||||
| 	 * | ||||
| 	 * <pre> | ||||
| 	 * @Configuration | ||||
| 	 * @EnableWebSecurity | ||||
| 	 * public class X509SecurityConfig extends WebSecurityConfigurerAdapter { | ||||
| 	 * | ||||
| 	 * 	@Override | ||||
| 	 * 	protected void configure(HttpSecurity http) throws Exception { | ||||
| 	 * 		http | ||||
| 	 * 			.authorizeRequests() | ||||
| 	 * 				.antMatchers("/**") | ||||
| 	 * 				.hasRole("USER") | ||||
| 	 * 				.and() | ||||
| 	 * 			.x509(withDefaults()); | ||||
| 	 * 	} | ||||
| 	 * } | ||||
| 	 * </pre> | ||||
| 	 * | ||||
| 	 * @param x509Customizer the {@link Customizer} to provide more options for | ||||
| 	 * the {@link X509Configurer} | ||||
| 	 * @return the {@link HttpSecurity} for further customizations | ||||
| 	 * @throws Exception | ||||
| 	 */ | ||||
| 	public HttpSecurity x509(Customizer<X509Configurer<HttpSecurity>> x509Customizer) throws Exception { | ||||
| 		x509Customizer.customize(getOrApply(new X509Configurer<>())); | ||||
| 		return HttpSecurity.this; | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Allows configuring of Remember Me authentication. | ||||
| 	 * | ||||
|  | ||||
| @ -38,6 +38,7 @@ import java.security.cert.X509Certificate; | ||||
| import static org.mockito.ArgumentMatchers.any; | ||||
| import static org.mockito.Mockito.spy; | ||||
| import static org.mockito.Mockito.verify; | ||||
| import static org.springframework.security.config.Customizer.withDefaults; | ||||
| import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.x509; | ||||
| import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated; | ||||
| import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; | ||||
| @ -122,6 +123,69 @@ public class X509ConfigurerTests { | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void x509WhenConfiguredInLambdaThenUsesDefaults() throws Exception { | ||||
| 		this.spring.register(DefaultsInLambdaConfig.class).autowire(); | ||||
| 		X509Certificate certificate = loadCert("rod.cer"); | ||||
| 
 | ||||
| 		this.mvc.perform(get("/") | ||||
| 				.with(x509(certificate))) | ||||
| 				.andExpect(authenticated().withUsername("rod")); | ||||
| 	} | ||||
| 
 | ||||
| 	@EnableWebSecurity | ||||
| 	static class DefaultsInLambdaConfig extends WebSecurityConfigurerAdapter { | ||||
| 		@Override | ||||
| 		protected void configure(HttpSecurity http) throws Exception { | ||||
| 			// @formatter:off | ||||
| 			http | ||||
| 				.x509(withDefaults()); | ||||
| 			// @formatter:on | ||||
| 		} | ||||
| 
 | ||||
| 		@Override | ||||
| 		protected void configure(AuthenticationManagerBuilder auth) throws Exception { | ||||
| 			// @formatter:off | ||||
| 			auth | ||||
| 				.inMemoryAuthentication() | ||||
| 					.withUser("rod").password("password").roles("USER", "ADMIN"); | ||||
| 			// @formatter:on | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void x509WhenSubjectPrincipalRegexInLambdaThenUsesRegexToExtractPrincipal() throws Exception { | ||||
| 		this.spring.register(SubjectPrincipalRegexInLambdaConfig.class).autowire(); | ||||
| 		X509Certificate certificate = loadCert("rodatexampledotcom.cer"); | ||||
| 
 | ||||
| 		this.mvc.perform(get("/") | ||||
| 				.with(x509(certificate))) | ||||
| 				.andExpect(authenticated().withUsername("rod")); | ||||
| 	} | ||||
| 
 | ||||
| 	@EnableWebSecurity | ||||
| 	static class SubjectPrincipalRegexInLambdaConfig extends WebSecurityConfigurerAdapter { | ||||
| 		@Override | ||||
| 		protected void configure(HttpSecurity http) throws Exception { | ||||
| 			// @formatter:off | ||||
| 			http | ||||
| 				.x509(x509 -> | ||||
| 					x509 | ||||
| 						.subjectPrincipalRegex("CN=(.*?)@example.com(?:,|$)") | ||||
| 				); | ||||
| 			// @formatter:on | ||||
| 		} | ||||
| 
 | ||||
| 		@Override | ||||
| 		protected void configure(AuthenticationManagerBuilder auth) throws Exception { | ||||
| 			// @formatter:off | ||||
| 			auth | ||||
| 				.inMemoryAuthentication() | ||||
| 					.withUser("rod").password("password").roles("USER", "ADMIN"); | ||||
| 			// @formatter:on | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	private <T extends Certificate> T loadCert(String location) { | ||||
| 		try (InputStream is = new ClassPathResource(location).getInputStream()) { | ||||
| 			CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user