SEC-883: RoleHierarchyVoter
http://jira.springframework.org/browse/SEC-883. Added RoleHierarchyVoter and deprecated existing approach. Also moved TestingAuthenticationToken to test package structure.
This commit is contained in:
parent
e982e91846
commit
1af7eed433
|
@ -25,6 +25,8 @@ import org.springframework.dao.DataAccessException;
|
||||||
* instead of only the directly assigned authorities.
|
* instead of only the directly assigned authorities.
|
||||||
*
|
*
|
||||||
* @author Michael Mayr
|
* @author Michael Mayr
|
||||||
|
* @deprecated use a {@link RoleHierarchyVoter} instead of populating the user Authentication object
|
||||||
|
* with the additional authorities.
|
||||||
*/
|
*/
|
||||||
public class UserDetailsServiceWrapper implements UserDetailsService {
|
public class UserDetailsServiceWrapper implements UserDetailsService {
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ import org.springframework.security.userdetails.UserDetails;
|
||||||
* delegated to the <tt>UserDetails</tt> implementation.
|
* delegated to the <tt>UserDetails</tt> implementation.
|
||||||
*
|
*
|
||||||
* @author Michael Mayr
|
* @author Michael Mayr
|
||||||
|
* @deprecated use a {@link RoleHierarchyVoter} instead.
|
||||||
*/
|
*/
|
||||||
public class UserDetailsWrapper implements UserDetails {
|
public class UserDetailsWrapper implements UserDetails {
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
package org.springframework.security.vote;
|
||||||
|
|
||||||
|
import org.springframework.security.Authentication;
|
||||||
|
import org.springframework.security.GrantedAuthority;
|
||||||
|
import org.springframework.security.userdetails.hierarchicalroles.RoleHierarchy;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extended RoleVoter which uses a {@link RoleHierarchy} definition to determine the
|
||||||
|
* roles allocated to the current user before voting.
|
||||||
|
*
|
||||||
|
* @author Luke Taylor
|
||||||
|
* @since 2.0.4
|
||||||
|
*/
|
||||||
|
public class RoleHierarchyVoter extends RoleVoter {
|
||||||
|
private RoleHierarchy roleHierarchy = null;
|
||||||
|
|
||||||
|
public RoleHierarchyVoter(RoleHierarchy roleHierarchy) {
|
||||||
|
Assert.notNull(roleHierarchy, "RoleHierarchy must not be null");
|
||||||
|
this.roleHierarchy = roleHierarchy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls the <tt>RoleHierarchy</tt> to obtain the complete set of user authorities.
|
||||||
|
*/
|
||||||
|
GrantedAuthority[] extractAuthorities(Authentication authentication) {
|
||||||
|
return roleHierarchy.getReachableGrantedAuthorities(authentication.getAuthorities());
|
||||||
|
}
|
||||||
|
}
|
|
@ -95,6 +95,7 @@ public class RoleVoter implements AccessDecisionVoter {
|
||||||
public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config) {
|
public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config) {
|
||||||
int result = ACCESS_ABSTAIN;
|
int result = ACCESS_ABSTAIN;
|
||||||
Iterator iter = config.getConfigAttributes().iterator();
|
Iterator iter = config.getConfigAttributes().iterator();
|
||||||
|
GrantedAuthority[] authorities = extractAuthorities(authentication);
|
||||||
|
|
||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
ConfigAttribute attribute = (ConfigAttribute) iter.next();
|
ConfigAttribute attribute = (ConfigAttribute) iter.next();
|
||||||
|
@ -102,7 +103,6 @@ public class RoleVoter implements AccessDecisionVoter {
|
||||||
if (this.supports(attribute)) {
|
if (this.supports(attribute)) {
|
||||||
result = ACCESS_DENIED;
|
result = ACCESS_DENIED;
|
||||||
|
|
||||||
GrantedAuthority[] authorities = authentication.getAuthorities();
|
|
||||||
// Attempt to find a matching granted authority
|
// Attempt to find a matching granted authority
|
||||||
for (int i = 0; i < authorities.length; i++) {
|
for (int i = 0; i < authorities.length; i++) {
|
||||||
if (attribute.getAttribute().equals(authorities[i].getAuthority())) {
|
if (attribute.getAttribute().equals(authorities[i].getAuthority())) {
|
||||||
|
@ -114,4 +114,8 @@ public class RoleVoter implements AccessDecisionVoter {
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GrantedAuthority[] extractAuthorities(Authentication authentication) {
|
||||||
|
return authentication.getAuthorities();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,8 +44,7 @@ public class SpringSecurityAuthenticationSourceTests {
|
||||||
@Test(expected=IllegalArgumentException.class)
|
@Test(expected=IllegalArgumentException.class)
|
||||||
public void getPrincipalRejectsNonLdapUserDetailsObject() {
|
public void getPrincipalRejectsNonLdapUserDetailsObject() {
|
||||||
AuthenticationSource source = new SpringSecurityAuthenticationSource();
|
AuthenticationSource source = new SpringSecurityAuthenticationSource();
|
||||||
SecurityContextHolder.getContext().setAuthentication(
|
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken(new Object(), "password"));
|
||||||
new TestingAuthenticationToken(new Object(), "password", null));
|
|
||||||
|
|
||||||
source.getPrincipal();
|
source.getPrincipal();
|
||||||
}
|
}
|
||||||
|
@ -53,8 +52,7 @@ public class SpringSecurityAuthenticationSourceTests {
|
||||||
@Test
|
@Test
|
||||||
public void expectedCredentialsAreReturned() {
|
public void expectedCredentialsAreReturned() {
|
||||||
AuthenticationSource source = new SpringSecurityAuthenticationSource();
|
AuthenticationSource source = new SpringSecurityAuthenticationSource();
|
||||||
SecurityContextHolder.getContext().setAuthentication(
|
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken(new Object(), "password"));
|
||||||
new TestingAuthenticationToken(new Object(), "password", null));
|
|
||||||
|
|
||||||
assertEquals("password", source.getCredentials());
|
assertEquals("password", source.getCredentials());
|
||||||
}
|
}
|
||||||
|
@ -66,7 +64,7 @@ public class SpringSecurityAuthenticationSourceTests {
|
||||||
user.setDn(new DistinguishedName("uid=joe,ou=users"));
|
user.setDn(new DistinguishedName("uid=joe,ou=users"));
|
||||||
AuthenticationSource source = new SpringSecurityAuthenticationSource();
|
AuthenticationSource source = new SpringSecurityAuthenticationSource();
|
||||||
SecurityContextHolder.getContext().setAuthentication(
|
SecurityContextHolder.getContext().setAuthentication(
|
||||||
new TestingAuthenticationToken(user.createUserDetails(), null, null));
|
new TestingAuthenticationToken(user.createUserDetails(), null));
|
||||||
|
|
||||||
assertEquals("uid=joe, ou=users", source.getPrincipal());
|
assertEquals("uid=joe, ou=users", source.getPrincipal());
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
package org.springframework.security.providers;
|
package org.springframework.security.providers;
|
||||||
|
|
||||||
import org.springframework.security.GrantedAuthority;
|
import org.springframework.security.GrantedAuthority;
|
||||||
|
import org.springframework.security.util.AuthorityUtils;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -34,6 +35,17 @@ public class TestingAuthenticationToken extends AbstractAuthenticationToken {
|
||||||
|
|
||||||
//~ Constructors ===================================================================================================
|
//~ Constructors ===================================================================================================
|
||||||
|
|
||||||
|
public TestingAuthenticationToken(Object principal, Object credentials) {
|
||||||
|
super(null);
|
||||||
|
this.principal = principal;
|
||||||
|
this.credentials = credentials;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public TestingAuthenticationToken(Object principal, Object credentials, String... authorities) {
|
||||||
|
this(principal, credentials, AuthorityUtils.stringArrayToAuthorityArray(authorities));
|
||||||
|
}
|
||||||
|
|
||||||
public TestingAuthenticationToken(Object principal, Object credentials, GrantedAuthority[] authorities) {
|
public TestingAuthenticationToken(Object principal, Object credentials, GrantedAuthority[] authorities) {
|
||||||
super(authorities);
|
super(authorities);
|
||||||
this.principal = principal;
|
this.principal = principal;
|
|
@ -1,77 +0,0 @@
|
||||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
|
||||||
*
|
|
||||||
* 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.providers;
|
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
|
||||||
|
|
||||||
import org.springframework.security.GrantedAuthority;
|
|
||||||
import org.springframework.security.GrantedAuthorityImpl;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests {@link TestingAuthenticationToken}.
|
|
||||||
*
|
|
||||||
* @author Ben Alex
|
|
||||||
* @version $Id$
|
|
||||||
*/
|
|
||||||
public class TestingAuthenticationTokenTests extends TestCase {
|
|
||||||
//~ Constructors ===================================================================================================
|
|
||||||
|
|
||||||
public TestingAuthenticationTokenTests() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public TestingAuthenticationTokenTests(String arg0) {
|
|
||||||
super(arg0);
|
|
||||||
}
|
|
||||||
|
|
||||||
//~ Methods ========================================================================================================
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
junit.textui.TestRunner.run(TestingAuthenticationTokenTests.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void setUp() throws Exception {
|
|
||||||
super.setUp();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testAuthenticated() {
|
|
||||||
TestingAuthenticationToken token = new TestingAuthenticationToken("Test", "Password", null);
|
|
||||||
assertTrue(!token.isAuthenticated());
|
|
||||||
token.setAuthenticated(true);
|
|
||||||
assertTrue(token.isAuthenticated());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testGetters() {
|
|
||||||
TestingAuthenticationToken token = new TestingAuthenticationToken("Test", "Password",
|
|
||||||
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")});
|
|
||||||
assertEquals("Test", token.getPrincipal());
|
|
||||||
assertEquals("Password", token.getCredentials());
|
|
||||||
assertEquals("ROLE_ONE", token.getAuthorities()[0].getAuthority());
|
|
||||||
assertEquals("ROLE_TWO", token.getAuthorities()[1].getAuthority());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testNoArgConstructorDoesntExist() {
|
|
||||||
Class clazz = TestingAuthenticationToken.class;
|
|
||||||
|
|
||||||
try {
|
|
||||||
clazz.getDeclaredConstructor((Class[]) null);
|
|
||||||
fail("Should have thrown NoSuchMethodException");
|
|
||||||
} catch (NoSuchMethodException expected) {
|
|
||||||
assertTrue(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -74,6 +74,6 @@ public class SessionFixationProtectionFilterTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void authenticateUser() {
|
private void authenticateUser() {
|
||||||
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "pass", null));
|
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "pass"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -160,7 +160,7 @@ public class RememberMeProcessingFilterTests extends TestCase {
|
||||||
public void testOnunsuccessfulLoginIsCalledWhenProviderRejectsAuth() throws Exception {
|
public void testOnunsuccessfulLoginIsCalledWhenProviderRejectsAuth() throws Exception {
|
||||||
Authentication remembered = new TestingAuthenticationToken("remembered", "password",
|
Authentication remembered = new TestingAuthenticationToken("remembered", "password",
|
||||||
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_REMEMBERED")});
|
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_REMEMBERED")});
|
||||||
final Authentication failedAuth = new TestingAuthenticationToken("failed", "", null);
|
final Authentication failedAuth = new TestingAuthenticationToken("failed", "");
|
||||||
|
|
||||||
RememberMeProcessingFilter filter = new RememberMeProcessingFilter() {
|
RememberMeProcessingFilter filter = new RememberMeProcessingFilter() {
|
||||||
protected void onUnsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) {
|
protected void onUnsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) {
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
package org.springframework.security.vote;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.springframework.security.ConfigAttributeDefinition;
|
||||||
|
import org.springframework.security.providers.TestingAuthenticationToken;
|
||||||
|
import org.springframework.security.userdetails.hierarchicalroles.RoleHierarchyImpl;
|
||||||
|
|
||||||
|
public class RoleHierarchyVoterTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void hierarchicalRoleIsIncludedInDecision() {
|
||||||
|
RoleHierarchyImpl roleHierarchyImpl = new RoleHierarchyImpl();
|
||||||
|
roleHierarchyImpl.setHierarchy("ROLE_A > ROLE_B");
|
||||||
|
|
||||||
|
// User has role A, role B is required
|
||||||
|
TestingAuthenticationToken auth = new TestingAuthenticationToken("user", "password", "ROLE_A");
|
||||||
|
RoleHierarchyVoter voter = new RoleHierarchyVoter(roleHierarchyImpl);
|
||||||
|
ConfigAttributeDefinition config = new ConfigAttributeDefinition("ROLE_B");
|
||||||
|
|
||||||
|
assertEquals(RoleHierarchyVoter.ACCESS_GRANTED, voter.vote(auth, new Object(), config));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue