mirror of
				https://github.com/spring-projects/spring-security.git
				synced 2025-10-30 22:28:46 +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; | ||||
| 
 | ||||
| import java.util.Collection; | ||||
| import java.util.List; | ||||
| import java.util.Arrays; | ||||
| import java.util.HashSet; | ||||
| import java.util.Set; | ||||
| 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; | ||||
| 
 | ||||
| /** | ||||
| @ -40,12 +38,12 @@ public final class AuthorityAuthorizationManager<T> implements AuthorizationMana | ||||
| 
 | ||||
| 	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) { | ||||
| 		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 | ||||
| 	 */ | ||||
| 	public void setRoleHierarchy(RoleHierarchy roleHierarchy) { | ||||
| 		Assert.notNull(roleHierarchy, "roleHierarchy cannot be null"); | ||||
| 		this.roleHierarchy = roleHierarchy; | ||||
| 		this.delegate.setRoleHierarchy(roleHierarchy); | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| @ -139,26 +136,7 @@ public final class AuthorityAuthorizationManager<T> implements AuthorizationMana | ||||
| 	 */ | ||||
| 	@Override | ||||
| 	public AuthorizationDecision check(Supplier<Authentication> authentication, T object) { | ||||
| 		boolean granted = isGranted(authentication.get()); | ||||
| 		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()); | ||||
| 		return this.delegate.check(authentication, this.authorities); | ||||
| 	} | ||||
| 
 | ||||
| 	@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"); | ||||
|  * 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. | ||||
|  * | ||||
|  * @author Luke Taylor | ||||
|  * @author Evgeniy Cheban | ||||
|  */ | ||||
| public final class AuthorityUtils { | ||||
| 
 | ||||
| @ -78,4 +79,18 @@ public final class AuthorityUtils { | ||||
| 		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"); | ||||
| 		RoleHierarchy roleHierarchy = new RoleHierarchyImpl(); | ||||
| 		manager.setRoleHierarchy(roleHierarchy); | ||||
| 		assertThat(manager).extracting("roleHierarchy").isEqualTo(roleHierarchy); | ||||
| 		assertThat(manager).extracting("delegate").extracting("roleHierarchy").isEqualTo(roleHierarchy); | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void getRoleHierarchyWhenNotSetThenDefaultsToNullRoleHierarchy() { | ||||
| 		AuthorityAuthorizationManager<Object> manager = AuthorityAuthorizationManager.hasRole("USER"); | ||||
| 		assertThat(manager).extracting("roleHierarchy").isInstanceOf(NullRoleHierarchy.class); | ||||
| 		assertThat(manager).extracting("delegate").extracting("roleHierarchy").isInstanceOf(NullRoleHierarchy.class); | ||||
| 	} | ||||
| 
 | ||||
| 	@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"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
| @ -16,6 +16,7 @@ | ||||
| 
 | ||||
| package org.springframework.security.core.authority; | ||||
| 
 | ||||
| import java.util.Arrays; | ||||
| import java.util.List; | ||||
| import java.util.Set; | ||||
| 
 | ||||
| @ -27,6 +28,7 @@ import static org.assertj.core.api.Assertions.assertThat; | ||||
| 
 | ||||
| /** | ||||
|  * @author Luke Taylor | ||||
|  * @author Evgeniy Cheban | ||||
|  */ | ||||
| public class AuthorityUtilsTests { | ||||
| 
 | ||||
| @ -42,4 +44,14 @@ public class AuthorityUtilsTests { | ||||
| 		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