mirror of
				https://github.com/spring-projects/spring-security.git
				synced 2025-10-31 06:38:42 +00:00 
			
		
		
		
	Add Authority String AuthorizationManager
Closes gh-12231
This commit is contained in:
		
							parent
							
								
									70a6cf6953
								
							
						
					
					
						commit
						855282ac3b
					
				| @ -0,0 +1,81 @@ | |||||||
|  | /* | ||||||
|  |  * Copyright 2002-2022 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. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | package org.springframework.security.authorization; | ||||||
|  | 
 | ||||||
|  | import java.util.Collection; | ||||||
|  | import java.util.function.Supplier; | ||||||
|  | 
 | ||||||
|  | import org.springframework.security.access.hierarchicalroles.NullRoleHierarchy; | ||||||
|  | import org.springframework.security.access.hierarchicalroles.RoleHierarchy; | ||||||
|  | import org.springframework.security.core.Authentication; | ||||||
|  | import org.springframework.security.core.GrantedAuthority; | ||||||
|  | import org.springframework.security.core.authority.AuthorityUtils; | ||||||
|  | import org.springframework.util.Assert; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * An {@link AuthorizationManager} that determines if the current user is authorized by | ||||||
|  |  * evaluating if the {@link Authentication} contains any of the specified authorities. | ||||||
|  |  * | ||||||
|  |  * @author Evgeniy Cheban | ||||||
|  |  * @since 6.1 | ||||||
|  |  */ | ||||||
|  | public final class AuthoritiesAuthorizationManager implements AuthorizationManager<Collection<String>> { | ||||||
|  | 
 | ||||||
|  | 	private RoleHierarchy roleHierarchy = new NullRoleHierarchy(); | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Sets the {@link RoleHierarchy} to be used. Default is {@link NullRoleHierarchy}. | ||||||
|  | 	 * Cannot be null. | ||||||
|  | 	 * @param roleHierarchy the {@link RoleHierarchy} to use | ||||||
|  | 	 */ | ||||||
|  | 	public void setRoleHierarchy(RoleHierarchy roleHierarchy) { | ||||||
|  | 		Assert.notNull(roleHierarchy, "roleHierarchy cannot be null"); | ||||||
|  | 		this.roleHierarchy = roleHierarchy; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Determines if the current user is authorized by evaluating if the | ||||||
|  | 	 * {@link Authentication} contains any of specified authorities. | ||||||
|  | 	 * @param authentication the {@link Supplier} of the {@link Authentication} to check | ||||||
|  | 	 * @param authorities the collection of authority strings to check | ||||||
|  | 	 * @return an {@link AuthorityAuthorizationDecision} | ||||||
|  | 	 */ | ||||||
|  | 	@Override | ||||||
|  | 	public AuthorityAuthorizationDecision check(Supplier<Authentication> authentication, | ||||||
|  | 			Collection<String> authorities) { | ||||||
|  | 		boolean granted = isGranted(authentication.get(), authorities); | ||||||
|  | 		return new AuthorityAuthorizationDecision(granted, AuthorityUtils.createAuthorityList(authorities)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	private boolean isGranted(Authentication authentication, Collection<String> authorities) { | ||||||
|  | 		return authentication != null && isAuthorized(authentication, authorities); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	private boolean isAuthorized(Authentication authentication, Collection<String> authorities) { | ||||||
|  | 		for (GrantedAuthority grantedAuthority : getGrantedAuthorities(authentication)) { | ||||||
|  | 			if (authorities.contains(grantedAuthority.getAuthority())) { | ||||||
|  | 				return true; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	private Collection<? extends GrantedAuthority> getGrantedAuthorities(Authentication authentication) { | ||||||
|  | 		return this.roleHierarchy.getReachableGrantedAuthorities(authentication.getAuthorities()); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -16,16 +16,14 @@ | |||||||
| 
 | 
 | ||||||
| package org.springframework.security.authorization; | package org.springframework.security.authorization; | ||||||
| 
 | 
 | ||||||
| import java.util.Collection; | import java.util.Arrays; | ||||||
| import java.util.List; | import java.util.HashSet; | ||||||
| import java.util.Set; | import java.util.Set; | ||||||
| import java.util.function.Supplier; | import java.util.function.Supplier; | ||||||
| 
 | 
 | ||||||
| import org.springframework.security.access.hierarchicalroles.NullRoleHierarchy; | import org.springframework.security.access.hierarchicalroles.NullRoleHierarchy; | ||||||
| import org.springframework.security.access.hierarchicalroles.RoleHierarchy; | import org.springframework.security.access.hierarchicalroles.RoleHierarchy; | ||||||
| import org.springframework.security.core.Authentication; | import org.springframework.security.core.Authentication; | ||||||
| import org.springframework.security.core.GrantedAuthority; |  | ||||||
| import org.springframework.security.core.authority.AuthorityUtils; |  | ||||||
| import org.springframework.util.Assert; | import org.springframework.util.Assert; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
| @ -40,12 +38,12 @@ public final class AuthorityAuthorizationManager<T> implements AuthorizationMana | |||||||
| 
 | 
 | ||||||
| 	private static final String ROLE_PREFIX = "ROLE_"; | 	private static final String ROLE_PREFIX = "ROLE_"; | ||||||
| 
 | 
 | ||||||
| 	private final List<GrantedAuthority> authorities; | 	private final AuthoritiesAuthorizationManager delegate = new AuthoritiesAuthorizationManager(); | ||||||
| 
 | 
 | ||||||
| 	private RoleHierarchy roleHierarchy = new NullRoleHierarchy(); | 	private final Set<String> authorities; | ||||||
| 
 | 
 | ||||||
| 	private AuthorityAuthorizationManager(String... authorities) { | 	private AuthorityAuthorizationManager(String... authorities) { | ||||||
| 		this.authorities = AuthorityUtils.createAuthorityList(authorities); | 		this.authorities = new HashSet<>(Arrays.asList(authorities)); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| @ -55,8 +53,7 @@ public final class AuthorityAuthorizationManager<T> implements AuthorizationMana | |||||||
| 	 * @since 5.8 | 	 * @since 5.8 | ||||||
| 	 */ | 	 */ | ||||||
| 	public void setRoleHierarchy(RoleHierarchy roleHierarchy) { | 	public void setRoleHierarchy(RoleHierarchy roleHierarchy) { | ||||||
| 		Assert.notNull(roleHierarchy, "roleHierarchy cannot be null"); | 		this.delegate.setRoleHierarchy(roleHierarchy); | ||||||
| 		this.roleHierarchy = roleHierarchy; |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| @ -139,26 +136,7 @@ public final class AuthorityAuthorizationManager<T> implements AuthorizationMana | |||||||
| 	 */ | 	 */ | ||||||
| 	@Override | 	@Override | ||||||
| 	public AuthorizationDecision check(Supplier<Authentication> authentication, T object) { | 	public AuthorizationDecision check(Supplier<Authentication> authentication, T object) { | ||||||
| 		boolean granted = isGranted(authentication.get()); | 		return this.delegate.check(authentication, this.authorities); | ||||||
| 		return new AuthorityAuthorizationDecision(granted, this.authorities); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	private boolean isGranted(Authentication authentication) { |  | ||||||
| 		return authentication != null && authentication.isAuthenticated() && isAuthorized(authentication); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	private boolean isAuthorized(Authentication authentication) { |  | ||||||
| 		Set<String> authorities = AuthorityUtils.authorityListToSet(this.authorities); |  | ||||||
| 		for (GrantedAuthority grantedAuthority : getGrantedAuthorities(authentication)) { |  | ||||||
| 			if (authorities.contains(grantedAuthority.getAuthority())) { |  | ||||||
| 				return true; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	private Collection<? extends GrantedAuthority> getGrantedAuthorities(Authentication authentication) { |  | ||||||
| 		return this.roleHierarchy.getReachableGrantedAuthorities(authentication.getAuthorities()); |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Override | 	@Override | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| /* | /* | ||||||
|  * Copyright 2002-2016 the original author or authors. |  * Copyright 2002-2022 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. | ||||||
| @ -33,6 +33,7 @@ import org.springframework.util.StringUtils; | |||||||
|  * Mainly intended for internal use. |  * Mainly intended for internal use. | ||||||
|  * |  * | ||||||
|  * @author Luke Taylor |  * @author Luke Taylor | ||||||
|  |  * @author Evgeniy Cheban | ||||||
|  */ |  */ | ||||||
| public final class AuthorityUtils { | public final class AuthorityUtils { | ||||||
| 
 | 
 | ||||||
| @ -78,4 +79,18 @@ public final class AuthorityUtils { | |||||||
| 		return grantedAuthorities; | 		return grantedAuthorities; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Converts authorities into a List of GrantedAuthority objects. | ||||||
|  | 	 * @param authorities the authorities to convert | ||||||
|  | 	 * @return a List of GrantedAuthority objects | ||||||
|  | 	 * @since 6.1 | ||||||
|  | 	 */ | ||||||
|  | 	public static List<GrantedAuthority> createAuthorityList(Collection<String> authorities) { | ||||||
|  | 		List<GrantedAuthority> grantedAuthorities = new ArrayList<>(authorities.size()); | ||||||
|  | 		for (String authority : authorities) { | ||||||
|  | 			grantedAuthorities.add(new SimpleGrantedAuthority(authority)); | ||||||
|  | 		} | ||||||
|  | 		return grantedAuthorities; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  | |||||||
| @ -0,0 +1,87 @@ | |||||||
|  | /* | ||||||
|  |  * Copyright 2002-2022 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. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | package org.springframework.security.authorization; | ||||||
|  | 
 | ||||||
|  | import java.util.Arrays; | ||||||
|  | import java.util.Collections; | ||||||
|  | import java.util.function.Supplier; | ||||||
|  | 
 | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | 
 | ||||||
|  | import org.springframework.security.access.hierarchicalroles.NullRoleHierarchy; | ||||||
|  | import org.springframework.security.access.hierarchicalroles.RoleHierarchy; | ||||||
|  | import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl; | ||||||
|  | import org.springframework.security.authentication.TestingAuthenticationToken; | ||||||
|  | import org.springframework.security.core.Authentication; | ||||||
|  | 
 | ||||||
|  | import static org.assertj.core.api.Assertions.assertThat; | ||||||
|  | import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Tests for {@link AuthoritiesAuthorizationManager}. | ||||||
|  |  * | ||||||
|  |  * @author Evgeniy Cheban | ||||||
|  |  */ | ||||||
|  | class AuthoritiesAuthorizationManagerTests { | ||||||
|  | 
 | ||||||
|  | 	@Test | ||||||
|  | 	void setRoleHierarchyWhenNullThenIllegalArgumentException() { | ||||||
|  | 		AuthoritiesAuthorizationManager manager = new AuthoritiesAuthorizationManager(); | ||||||
|  | 		assertThatIllegalArgumentException().isThrownBy(() -> manager.setRoleHierarchy(null)) | ||||||
|  | 				.withMessage("roleHierarchy cannot be null"); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Test | ||||||
|  | 	void setRoleHierarchyWhenNotNullThenVerifyRoleHierarchy() { | ||||||
|  | 		AuthoritiesAuthorizationManager manager = new AuthoritiesAuthorizationManager(); | ||||||
|  | 		RoleHierarchy roleHierarchy = new RoleHierarchyImpl(); | ||||||
|  | 		manager.setRoleHierarchy(roleHierarchy); | ||||||
|  | 		assertThat(manager).extracting("roleHierarchy").isEqualTo(roleHierarchy); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Test | ||||||
|  | 	void getRoleHierarchyWhenNotSetThenDefaultsToNullRoleHierarchy() { | ||||||
|  | 		AuthoritiesAuthorizationManager manager = new AuthoritiesAuthorizationManager(); | ||||||
|  | 		assertThat(manager).extracting("roleHierarchy").isInstanceOf(NullRoleHierarchy.class); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Test | ||||||
|  | 	void checkWhenUserHasAnyAuthorityThenGrantedDecision() { | ||||||
|  | 		AuthoritiesAuthorizationManager manager = new AuthoritiesAuthorizationManager(); | ||||||
|  | 		Supplier<Authentication> authentication = () -> new TestingAuthenticationToken("user", "password", "USER"); | ||||||
|  | 		assertThat(manager.check(authentication, Arrays.asList("ADMIN", "USER")).isGranted()).isTrue(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Test | ||||||
|  | 	void checkWhenUserHasNotAnyAuthorityThenDeniedDecision() { | ||||||
|  | 		AuthoritiesAuthorizationManager manager = new AuthoritiesAuthorizationManager(); | ||||||
|  | 		Supplier<Authentication> authentication = () -> new TestingAuthenticationToken("user", "password", "ANONYMOUS"); | ||||||
|  | 		assertThat(manager.check(authentication, Arrays.asList("ADMIN", "USER")).isGranted()).isFalse(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Test | ||||||
|  | 	void hasRoleWhenRoleHierarchySetThenGreaterRoleTakesPrecedence() { | ||||||
|  | 		AuthoritiesAuthorizationManager manager = new AuthoritiesAuthorizationManager(); | ||||||
|  | 		RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl(); | ||||||
|  | 		roleHierarchy.setHierarchy("ROLE_ADMIN > ROLE_USER"); | ||||||
|  | 		manager.setRoleHierarchy(roleHierarchy); | ||||||
|  | 		Supplier<Authentication> authentication = () -> new TestingAuthenticationToken("user", "password", | ||||||
|  | 				"ROLE_ADMIN"); | ||||||
|  | 		assertThat(manager.check(authentication, Collections.singleton("ROLE_ADMIN")).isGranted()).isTrue(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -226,13 +226,13 @@ public class AuthorityAuthorizationManagerTests { | |||||||
| 		AuthorityAuthorizationManager<Object> manager = AuthorityAuthorizationManager.hasRole("USER"); | 		AuthorityAuthorizationManager<Object> manager = AuthorityAuthorizationManager.hasRole("USER"); | ||||||
| 		RoleHierarchy roleHierarchy = new RoleHierarchyImpl(); | 		RoleHierarchy roleHierarchy = new RoleHierarchyImpl(); | ||||||
| 		manager.setRoleHierarchy(roleHierarchy); | 		manager.setRoleHierarchy(roleHierarchy); | ||||||
| 		assertThat(manager).extracting("roleHierarchy").isEqualTo(roleHierarchy); | 		assertThat(manager).extracting("delegate").extracting("roleHierarchy").isEqualTo(roleHierarchy); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Test | 	@Test | ||||||
| 	public void getRoleHierarchyWhenNotSetThenDefaultsToNullRoleHierarchy() { | 	public void getRoleHierarchyWhenNotSetThenDefaultsToNullRoleHierarchy() { | ||||||
| 		AuthorityAuthorizationManager<Object> manager = AuthorityAuthorizationManager.hasRole("USER"); | 		AuthorityAuthorizationManager<Object> manager = AuthorityAuthorizationManager.hasRole("USER"); | ||||||
| 		assertThat(manager).extracting("roleHierarchy").isInstanceOf(NullRoleHierarchy.class); | 		assertThat(manager).extracting("delegate").extracting("roleHierarchy").isInstanceOf(NullRoleHierarchy.class); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Test | 	@Test | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| /* | /* | ||||||
|  * Copyright 2002-2016 the original author or authors. |  * Copyright 2002-2022 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,6 +16,7 @@ | |||||||
| 
 | 
 | ||||||
| package org.springframework.security.core.authority; | package org.springframework.security.core.authority; | ||||||
| 
 | 
 | ||||||
|  | import java.util.Arrays; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.Set; | import java.util.Set; | ||||||
| 
 | 
 | ||||||
| @ -27,6 +28,7 @@ import static org.assertj.core.api.Assertions.assertThat; | |||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * @author Luke Taylor |  * @author Luke Taylor | ||||||
|  |  * @author Evgeniy Cheban | ||||||
|  */ |  */ | ||||||
| public class AuthorityUtilsTests { | public class AuthorityUtilsTests { | ||||||
| 
 | 
 | ||||||
| @ -42,4 +44,14 @@ public class AuthorityUtilsTests { | |||||||
| 		assertThat(authorities.contains("ROLE_D")).isTrue(); | 		assertThat(authorities.contains("ROLE_D")).isTrue(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	@Test | ||||||
|  | 	public void createAuthorityList() { | ||||||
|  | 		List<GrantedAuthority> authorities = AuthorityUtils | ||||||
|  | 				.createAuthorityList(Arrays.asList("ROLE_A", "ROLE_B", "ROLE_C")); | ||||||
|  | 		assertThat(authorities).hasSize(3); | ||||||
|  | 		assertThat(authorities).element(0).extracting(GrantedAuthority::getAuthority).isEqualTo("ROLE_A"); | ||||||
|  | 		assertThat(authorities).element(1).extracting(GrantedAuthority::getAuthority).isEqualTo("ROLE_B"); | ||||||
|  | 		assertThat(authorities).element(2).extracting(GrantedAuthority::getAuthority).isEqualTo("ROLE_C"); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user