mirror of
				https://github.com/spring-projects/spring-security.git
				synced 2025-10-30 22:28:46 +00:00 
			
		
		
		
	PasswordEncoder as Bean default for XML
Issue: gh-4873
This commit is contained in:
		
							parent
							
								
									f558b5016c
								
							
						
					
					
						commit
						9afee9e4e2
					
				| @ -26,6 +26,7 @@ import org.springframework.security.authentication.ProviderManager; | ||||
| import org.springframework.security.authentication.dao.DaoAuthenticationProvider; | ||||
| import org.springframework.security.config.BeanIds; | ||||
| import org.springframework.security.core.userdetails.UserDetailsService; | ||||
| import org.springframework.security.crypto.password.PasswordEncoder; | ||||
| 
 | ||||
| import java.util.Arrays; | ||||
| 
 | ||||
| @ -49,21 +50,24 @@ public class AuthenticationManagerFactoryBean implements | ||||
| 			return (AuthenticationManager) bf.getBean(BeanIds.AUTHENTICATION_MANAGER); | ||||
| 		} | ||||
| 		catch (NoSuchBeanDefinitionException e) { | ||||
| 			if (BeanIds.AUTHENTICATION_MANAGER.equals(e.getBeanName())) { | ||||
| 				try { | ||||
| 					UserDetailsService uds = bf.getBean(UserDetailsService.class); | ||||
| 					DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); | ||||
| 					provider.setUserDetailsService(uds); | ||||
| 					provider.afterPropertiesSet(); | ||||
| 					return new ProviderManager( | ||||
| 							Arrays.<AuthenticationProvider> asList(provider)); | ||||
| 				} | ||||
| 				catch (NoSuchBeanDefinitionException noUds) { | ||||
| 				} | ||||
| 				throw new NoSuchBeanDefinitionException(BeanIds.AUTHENTICATION_MANAGER, | ||||
| 						MISSING_BEAN_ERROR_MESSAGE); | ||||
| 			if (!BeanIds.AUTHENTICATION_MANAGER.equals(e.getBeanName())) { | ||||
| 				throw e; | ||||
| 			} | ||||
| 			throw e; | ||||
| 
 | ||||
| 			UserDetailsService uds = getBeanOrNull(UserDetailsService.class); | ||||
| 			if(uds == null) { | ||||
| 				throw new NoSuchBeanDefinitionException(BeanIds.AUTHENTICATION_MANAGER, | ||||
| 					MISSING_BEAN_ERROR_MESSAGE); | ||||
| 			} | ||||
| 
 | ||||
| 			DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); | ||||
| 			provider.setUserDetailsService(uds); | ||||
| 			PasswordEncoder passwordEncoder = getBeanOrNull(PasswordEncoder.class); | ||||
| 			if (passwordEncoder != null) { | ||||
| 				provider.setPasswordEncoder(passwordEncoder); | ||||
| 			} | ||||
| 			provider.afterPropertiesSet(); | ||||
| 			return new ProviderManager(Arrays.<AuthenticationProvider> asList(provider)); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| @ -79,4 +83,11 @@ public class AuthenticationManagerFactoryBean implements | ||||
| 		bf = beanFactory; | ||||
| 	} | ||||
| 
 | ||||
| 	private <T> T getBeanOrNull(Class<T> type) { | ||||
| 		try { | ||||
| 			return this.bf.getBean(type); | ||||
| 		} catch (NoSuchBeanDefinitionException noUds) { | ||||
| 			return null; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -15,6 +15,7 @@ | ||||
|  */ | ||||
| package org.springframework.security.config.authentication; | ||||
| 
 | ||||
| import org.springframework.beans.BeanMetadataElement; | ||||
| import org.springframework.beans.factory.config.BeanDefinition; | ||||
| import org.springframework.beans.factory.config.RuntimeBeanReference; | ||||
| import org.springframework.beans.factory.support.RootBeanDefinition; | ||||
| @ -36,17 +37,16 @@ public class AuthenticationProviderBeanDefinitionParser implements BeanDefinitio | ||||
| 	private static final String ATT_USER_DETAILS_REF = "user-service-ref"; | ||||
| 
 | ||||
| 	public BeanDefinition parse(Element element, ParserContext pc) { | ||||
| 		RootBeanDefinition authProvider = new RootBeanDefinition( | ||||
| 				DaoAuthenticationProvider.class); | ||||
| 		RootBeanDefinition authProvider = new RootBeanDefinition(DaoAuthenticationProvider.class); | ||||
| 		authProvider.setSource(pc.extractSource(element)); | ||||
| 
 | ||||
| 		Element passwordEncoderElt = DomUtils.getChildElementByTagName(element, | ||||
| 				Elements.PASSWORD_ENCODER); | ||||
| 		Element passwordEncoderElt = DomUtils.getChildElementByTagName(element, Elements.PASSWORD_ENCODER); | ||||
| 
 | ||||
| 		if (passwordEncoderElt != null) { | ||||
| 			PasswordEncoderParser pep = new PasswordEncoderParser(passwordEncoderElt, pc); | ||||
| 			authProvider.getPropertyValues().addPropertyValue("passwordEncoder", | ||||
| 					pep.getPasswordEncoder()); | ||||
| 		PasswordEncoderParser pep = new PasswordEncoderParser(passwordEncoderElt, pc); | ||||
| 		BeanMetadataElement passwordEncoder = pep.getPasswordEncoder(); | ||||
| 		if (passwordEncoder != null) { | ||||
| 			authProvider.getPropertyValues() | ||||
| 				.addPropertyValue("passwordEncoder", passwordEncoder); | ||||
| 		} | ||||
| 
 | ||||
| 		Element userServiceElt = DomUtils.getChildElementByTagName(element, | ||||
|  | ||||
| @ -56,6 +56,12 @@ public class PasswordEncoderParser { | ||||
| 	} | ||||
| 
 | ||||
| 	private void parse(Element element, ParserContext parserContext) { | ||||
| 		if (element == null) { | ||||
| 			if (parserContext.getRegistry().containsBeanDefinition("passwordEncoder")) { | ||||
| 				this.passwordEncoder = parserContext.getRegistry().getBeanDefinition("passwordEncoder"); | ||||
| 			} | ||||
| 			return; | ||||
| 		} | ||||
| 		String hash = element.getAttribute(ATT_HASH); | ||||
| 		boolean useBase64 = false; | ||||
| 
 | ||||
|  | ||||
| @ -15,25 +15,27 @@ | ||||
|  */ | ||||
| package org.springframework.security.config.authentication; | ||||
| 
 | ||||
| import static org.assertj.core.api.Assertions.*; | ||||
| 
 | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import org.junit.Rule; | ||||
| import org.junit.Test; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.context.ApplicationListener; | ||||
| import org.springframework.context.ConfigurableApplicationContext; | ||||
| import org.springframework.context.support.AbstractXmlApplicationContext; | ||||
| import org.springframework.security.authentication.AuthenticationProvider; | ||||
| import org.springframework.security.authentication.DefaultAuthenticationEventPublisher; | ||||
| import org.springframework.security.authentication.ProviderManager; | ||||
| import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; | ||||
| import org.springframework.security.authentication.event.AbstractAuthenticationEvent; | ||||
| import org.springframework.security.config.test.SpringTestContext; | ||||
| import org.springframework.security.config.test.SpringTestRule; | ||||
| import org.springframework.security.config.util.InMemoryXmlApplicationContext; | ||||
| import org.springframework.security.util.FieldUtils; | ||||
| import org.springframework.test.web.servlet.MockMvc; | ||||
| 
 | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import static org.assertj.core.api.Assertions.assertThat; | ||||
| import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic; | ||||
| import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; | ||||
| import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; | ||||
| 
 | ||||
| /** | ||||
|  * | ||||
| @ -44,7 +46,8 @@ public class AuthenticationManagerBeanDefinitionParserTests { | ||||
| 			+ "    <authentication-provider>" | ||||
| 			+ "        <user-service>" | ||||
| 			+ "            <user name='bob' password='{noop}bobspassword' authorities='ROLE_A,ROLE_B' />" | ||||
| 			+ "        </user-service>" + "    </authentication-provider>" | ||||
| 			+ "        </user-service>" | ||||
| 			+ "    </authentication-provider>" | ||||
| 			+ "</authentication-manager>"; | ||||
| 	@Rule | ||||
| 	public final SpringTestRule spring = new SpringTestRule(); | ||||
| @ -92,6 +95,23 @@ public class AuthenticationManagerBeanDefinitionParserTests { | ||||
| 		assertThat(pm.isEraseCredentialsAfterAuthentication()).isFalse(); | ||||
| 	} | ||||
| 
 | ||||
| 	@Autowired | ||||
| 	MockMvc mockMvc; | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void passwordEncoderBeanUsed() throws Exception { | ||||
| 		this.spring.context("<b:bean id='passwordEncoder' class='org.springframework.security.crypto.password.NoOpPasswordEncoder' factory-method='getInstance'/>" | ||||
| 			+ "<user-service>" | ||||
| 			+ "  <user name='user' password='password' authorities='ROLE_A,ROLE_B' />" | ||||
| 			+ "</user-service>" | ||||
| 			+ "<http/>") | ||||
| 			.mockMvcAfterSpringSecurityOk() | ||||
| 			.autowire(); | ||||
| 
 | ||||
| 		this.mockMvc.perform(get("/").with(httpBasic("user", "password"))) | ||||
| 			.andExpect(status().isOk()); | ||||
| 	} | ||||
| 
 | ||||
| 	private static class AuthListener implements | ||||
| 			ApplicationListener<AbstractAuthenticationEvent> { | ||||
| 		List<AbstractAuthenticationEvent> events = new ArrayList<AbstractAuthenticationEvent>(); | ||||
|  | ||||
| @ -0,0 +1,60 @@ | ||||
| /* | ||||
|  * Copyright 2002-2017 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 | ||||
|  * | ||||
|  *      http://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. | ||||
|  */ | ||||
| 
 | ||||
| package org.springframework.security.config.authentication; | ||||
| 
 | ||||
| import org.junit.Rule; | ||||
| import org.junit.Test; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.security.config.test.SpringTestRule; | ||||
| import org.springframework.test.web.servlet.MockMvc; | ||||
| 
 | ||||
| import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic; | ||||
| import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; | ||||
| import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; | ||||
| 
 | ||||
| /** | ||||
|  * @author Rob Winch | ||||
|  * @since 5.0 | ||||
|  */ | ||||
| public class PasswordEncoderParserTests { | ||||
| 	@Rule | ||||
| 	public final SpringTestRule spring = new SpringTestRule(); | ||||
| 
 | ||||
| 	@Autowired | ||||
| 	MockMvc mockMvc; | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void passwordEncoderDefaultsToDelegatingPasswordEncoder() throws Exception { | ||||
| 		this.spring.configLocations("classpath:org/springframework/security/config/authentication/PasswordEncoderParserTests-default.xml") | ||||
| 			.mockMvcAfterSpringSecurityOk() | ||||
| 			.autowire(); | ||||
| 
 | ||||
| 		this.mockMvc.perform(get("/").with(httpBasic("user", "password"))) | ||||
| 			.andExpect(status().isOk()); | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void passwordEncoderDefaultsToPasswordEncoderBean() throws Exception { | ||||
| 		this.spring.configLocations("classpath:org/springframework/security/config/authentication/PasswordEncoderParserTests-bean.xml") | ||||
| 			.mockMvcAfterSpringSecurityOk() | ||||
| 			.autowire(); | ||||
| 
 | ||||
| 		this.mockMvc.perform(get("/").with(httpBasic("user", "password"))) | ||||
| 			.andExpect(status().isOk()); | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,34 @@ | ||||
| <!-- | ||||
|   ~ Copyright 2002-2017 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 | ||||
|   ~ | ||||
|   ~      http://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="http://www.springframework.org/schema/security" | ||||
| 		 xmlns:b="http://www.springframework.org/schema/beans" | ||||
| 		 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||
| 		 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd | ||||
| 						http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd"> | ||||
| 
 | ||||
| 	<b:bean id="passwordEncoder" class="org.springframework.security.crypto.password.NoOpPasswordEncoder" factory-method="getInstance"/> | ||||
| 
 | ||||
| 	<http /> | ||||
| 
 | ||||
| 	<authentication-manager> | ||||
| 		<authentication-provider> | ||||
| 			<user-service> | ||||
| 				<user name="user" password="password" authorities="ROLE_USER" /> | ||||
| 			</user-service> | ||||
| 		</authentication-provider> | ||||
| 	</authentication-manager> | ||||
| </b:beans> | ||||
| @ -0,0 +1,15 @@ | ||||
| <b:beans xmlns="http://www.springframework.org/schema/security" | ||||
| 		 xmlns:b="http://www.springframework.org/schema/beans" | ||||
| 		 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||
| 		 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd | ||||
| 						http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd"> | ||||
| 	<http /> | ||||
| 
 | ||||
| 	<authentication-manager> | ||||
| 		<authentication-provider> | ||||
| 			<user-service> | ||||
| 				<user name="user" password="{noop}password" authorities="ROLE_USER" /> | ||||
| 			</user-service> | ||||
| 		</authentication-provider> | ||||
| 	</authentication-manager> | ||||
| </b:beans> | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user