Corrected Authz parsing of whitespace in GrantedAuthoritys. Contributed by Francois Beausoleil.
This commit is contained in:
parent
632617f693
commit
52c42a7a40
|
@ -16,10 +16,13 @@
|
||||||
package net.sf.acegisecurity.taglibs.authz;
|
package net.sf.acegisecurity.taglibs.authz;
|
||||||
|
|
||||||
import net.sf.acegisecurity.Authentication;
|
import net.sf.acegisecurity.Authentication;
|
||||||
|
import net.sf.acegisecurity.GrantedAuthority;
|
||||||
import net.sf.acegisecurity.GrantedAuthorityImpl;
|
import net.sf.acegisecurity.GrantedAuthorityImpl;
|
||||||
import net.sf.acegisecurity.context.ContextHolder;
|
import net.sf.acegisecurity.context.ContextHolder;
|
||||||
import net.sf.acegisecurity.context.security.SecureContext;
|
import net.sf.acegisecurity.context.security.SecureContext;
|
||||||
|
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import org.springframework.web.util.ExpressionEvaluationUtils;
|
import org.springframework.web.util.ExpressionEvaluationUtils;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
@ -132,24 +135,104 @@ public class AuthorizeTag extends TagSupport {
|
||||||
return granted;
|
return granted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Set authoritiesToRoles(Collection c) {
|
||||||
|
Set target = new HashSet();
|
||||||
|
|
||||||
|
for (Iterator iterator = c.iterator(); iterator.hasNext();) {
|
||||||
|
GrantedAuthority authority = (GrantedAuthority) iterator.next();
|
||||||
|
|
||||||
|
if (null == authority.getAuthority()) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Cannot process GrantedAuthority objects which return null from getAuthority() - attempting to process "
|
||||||
|
+ authority.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
target.add(authority.getAuthority());
|
||||||
|
}
|
||||||
|
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
private Set parseAuthoritiesString(String authorizationsString) {
|
private Set parseAuthoritiesString(String authorizationsString) {
|
||||||
final Set requiredAuthorities = new HashSet();
|
final Set requiredAuthorities = new HashSet();
|
||||||
final StringTokenizer tokenizer;
|
final String[] authorities = StringUtils
|
||||||
tokenizer = new StringTokenizer(authorizationsString, ",", false);
|
.commaDelimitedListToStringArray(authorizationsString);
|
||||||
|
|
||||||
while (tokenizer.hasMoreTokens()) {
|
for (int i = 0; i < authorities.length; i++) {
|
||||||
String role = tokenizer.nextToken();
|
String authority = authorities[i];
|
||||||
requiredAuthorities.add(new GrantedAuthorityImpl(role.trim()));
|
String role = authority.replaceAll("\\s+", "");
|
||||||
|
requiredAuthorities.add(new GrantedAuthorityImpl(role));
|
||||||
}
|
}
|
||||||
|
|
||||||
return requiredAuthorities;
|
return requiredAuthorities;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Set retainAll(final Collection granted,
|
/**
|
||||||
final Set requiredAuthorities) {
|
* Find the common authorities between the current authentication's {@link
|
||||||
Set grantedCopy = new HashSet(granted);
|
* GrantedAuthority} and the ones that have been specified in the tag's
|
||||||
grantedCopy.retainAll(requiredAuthorities);
|
* ifAny, ifNot or ifAllGranted attributes.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* We need to manually iterate over both collections, because the granted
|
||||||
|
* authorities might not implement {@link Object#equals(Object)} and
|
||||||
|
* {@link Object#hashCode()} in the same way as {@link
|
||||||
|
* GrantedAuthorityImpl}, thereby invalidating {@link
|
||||||
|
* Collection#retainAll(java.util.Collection)} results.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* <strong>CAVEAT</strong>: This method <strong>will not</strong> work if
|
||||||
|
* the granted authorities returns a <code>null</code> string as the
|
||||||
|
* return value of {@link
|
||||||
|
* net.sf.acegisecurity.GrantedAuthority#getAuthority()}.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Reported by rawdave, on Fri Feb 04, 2005 2:11 pm in the Acegi Security
|
||||||
|
* System for Spring forums.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param granted The authorities granted by the authentication. May be any
|
||||||
|
* implementation of {@link GrantedAuthority} that does
|
||||||
|
* <strong>not</strong> return <code>null</code> from {@link
|
||||||
|
* net.sf.acegisecurity.GrantedAuthority#getAuthority()}.
|
||||||
|
* @param required A {@link Set} of {@link GrantedAuthorityImpl}s that have
|
||||||
|
* been built using ifAny, ifAll or ifNotGranted.
|
||||||
|
*
|
||||||
|
* @return A set containing only the common authorities between
|
||||||
|
* <var>granted</var> and <var>required</var>.
|
||||||
|
*
|
||||||
|
* @see <a
|
||||||
|
* href="http://forum.springframework.org/viewtopic.php?t=3367">authz:authorize
|
||||||
|
* ifNotGranted not behaving as expected</a>
|
||||||
|
*/
|
||||||
|
private Set retainAll(final Collection granted, final Set required) {
|
||||||
|
Set grantedRoles = authoritiesToRoles(granted);
|
||||||
|
Set requiredRoles = authoritiesToRoles(required);
|
||||||
|
grantedRoles.retainAll(requiredRoles);
|
||||||
|
|
||||||
return grantedCopy;
|
return rolesToAuthorities(grantedRoles, granted);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set rolesToAuthorities(Set grantedRoles, Collection granted) {
|
||||||
|
Set target = new HashSet();
|
||||||
|
|
||||||
|
for (Iterator iterator = grantedRoles.iterator(); iterator.hasNext();) {
|
||||||
|
String role = (String) iterator.next();
|
||||||
|
|
||||||
|
for (Iterator grantedIterator = granted.iterator();
|
||||||
|
grantedIterator.hasNext();) {
|
||||||
|
GrantedAuthority authority = (GrantedAuthority) grantedIterator
|
||||||
|
.next();
|
||||||
|
|
||||||
|
if (authority.getAuthority().equals(role)) {
|
||||||
|
target.add(authority);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return target;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
/* Copyright 2004, 2005 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 net.sf.acegisecurity.taglibs.authz;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import net.sf.acegisecurity.GrantedAuthority;
|
||||||
|
import net.sf.acegisecurity.context.ContextHolder;
|
||||||
|
import net.sf.acegisecurity.context.security.SecureContextImpl;
|
||||||
|
import net.sf.acegisecurity.providers.TestingAuthenticationToken;
|
||||||
|
|
||||||
|
import javax.servlet.jsp.JspException;
|
||||||
|
import javax.servlet.jsp.tagext.Tag;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DOCUMENT ME!
|
||||||
|
*
|
||||||
|
* @author Francois Beausoleil
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class AuthorizeTagCustomGrantedAuthorityTests extends TestCase {
|
||||||
|
//~ Instance fields ========================================================
|
||||||
|
|
||||||
|
private final AuthorizeTag authorizeTag = new AuthorizeTag();
|
||||||
|
private SecureContextImpl context;
|
||||||
|
private TestingAuthenticationToken currentUser;
|
||||||
|
|
||||||
|
//~ Methods ================================================================
|
||||||
|
|
||||||
|
public void testAllowsRequestWhenCustomAuthorityPresentsCorrectRole()
|
||||||
|
throws JspException {
|
||||||
|
authorizeTag.setIfAnyGranted("ROLE_TELLER");
|
||||||
|
assertEquals("authorized - ROLE_TELLER in both sets",
|
||||||
|
Tag.EVAL_BODY_INCLUDE, authorizeTag.doStartTag());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testRejectsRequestWhenCustomAuthorityReturnsNull()
|
||||||
|
throws JspException {
|
||||||
|
authorizeTag.setIfAnyGranted("ROLE_TELLER");
|
||||||
|
context.setAuthentication(new TestingAuthenticationToken("abc", "123",
|
||||||
|
new GrantedAuthority[] {new CustomGrantedAuthority(null)}));
|
||||||
|
|
||||||
|
try {
|
||||||
|
authorizeTag.doStartTag();
|
||||||
|
fail("Failed to reject GrantedAuthority with NULL getAuthority()");
|
||||||
|
} catch (IllegalArgumentException expected) {
|
||||||
|
assertTrue("expected", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
|
||||||
|
currentUser = new TestingAuthenticationToken("abc", "123",
|
||||||
|
new GrantedAuthority[] {new CustomGrantedAuthority(
|
||||||
|
"ROLE_TELLER")});
|
||||||
|
|
||||||
|
context = new SecureContextImpl();
|
||||||
|
context.setAuthentication(currentUser);
|
||||||
|
|
||||||
|
ContextHolder.setContext(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void tearDown() throws Exception {
|
||||||
|
ContextHolder.setContext(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
//~ Inner Classes ==========================================================
|
||||||
|
|
||||||
|
private static class CustomGrantedAuthority implements GrantedAuthority {
|
||||||
|
private final String authority;
|
||||||
|
|
||||||
|
public CustomGrantedAuthority(String authority) {
|
||||||
|
this.authority = authority;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAuthority() {
|
||||||
|
return authority;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,6 +28,7 @@
|
||||||
<release version="0.8.1" date="In CVS">
|
<release version="0.8.1" date="In CVS">
|
||||||
<action dev="benalex" type="fix">SecurityEnforcementFilter caused NullPointerException when anonymous authentication used with BasicProcessingFilterEntryPoint</action>
|
<action dev="benalex" type="fix">SecurityEnforcementFilter caused NullPointerException when anonymous authentication used with BasicProcessingFilterEntryPoint</action>
|
||||||
<action dev="benalex" type="fix">FilterChainProxy now supports replacement of ServletRequest and ServetResponse by Filter beans</action>
|
<action dev="benalex" type="fix">FilterChainProxy now supports replacement of ServletRequest and ServetResponse by Filter beans</action>
|
||||||
|
<action dev="benalex" type="fix">Corrected Authz parsing of whitespace in GrantedAuthoritys</action>
|
||||||
<action dev="benalex" type="update">ContextHolderAwareRequestWrapper methods returns null if user is anonymous</action>
|
<action dev="benalex" type="update">ContextHolderAwareRequestWrapper methods returns null if user is anonymous</action>
|
||||||
<action dev="benalex" type="update">AbstractBasicAclEntry improved compatibility with Hibernate</action>
|
<action dev="benalex" type="update">AbstractBasicAclEntry improved compatibility with Hibernate</action>
|
||||||
</release>
|
</release>
|
||||||
|
|
Loading…
Reference in New Issue