diff --git a/samples/tutorial/src/main/webapp/secure/extreme/index.jsp b/samples/tutorial/src/main/webapp/secure/extreme/index.jsp index 93f7a17cfc..a629b69853 100644 --- a/samples/tutorial/src/main/webapp/secure/extreme/index.jsp +++ b/samples/tutorial/src/main/webapp/secure/extreme/index.jsp @@ -5,11 +5,11 @@

VERY Secure Page

This is a protected page. You can only see me if you are a supervisor. - + You have "ROLE_SUPERVISOR" (this text is surrounded by <authz:authorize> tags).

Home

Logout - \ No newline at end of file + diff --git a/samples/tutorial/src/main/webapp/secure/index.jsp b/samples/tutorial/src/main/webapp/secure/index.jsp index e44be8bcd7..8fa5039644 100644 --- a/samples/tutorial/src/main/webapp/secure/index.jsp +++ b/samples/tutorial/src/main/webapp/secure/index.jsp @@ -8,8 +8,8 @@ This is a protected page. You can get to me if you've been remembered, or if you've authenticated this session.

- - You are a supervisor! You can therefore see the extremely secure page.

+ + You are a supervisor! You can therefore see the extremely secure page.

Properties obtained using <sec:authentication /> tag

@@ -33,4 +33,4 @@ or if you've authenticated this session.

Home

Logout - \ No newline at end of file + diff --git a/taglibs/src/main/java/org/springframework/security/taglibs/authz/AuthorizeTag.java b/taglibs/src/main/java/org/springframework/security/taglibs/authz/AuthorizeTag.java index cfef55ad36..1caf3e5d24 100644 --- a/taglibs/src/main/java/org/springframework/security/taglibs/authz/AuthorizeTag.java +++ b/taglibs/src/main/java/org/springframework/security/taglibs/authz/AuthorizeTag.java @@ -1,197 +1,87 @@ -/* 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.taglibs.authz; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; +import java.io.IOException; +import java.util.Map; +import javax.servlet.FilterChain; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; import javax.servlet.jsp.JspException; -import javax.servlet.jsp.tagext.Tag; -import javax.servlet.jsp.tagext.TagSupport; +import org.springframework.context.ApplicationContext; +import org.springframework.expression.Expression; +import org.springframework.expression.ParseException; +import org.springframework.security.access.expression.ExpressionUtils; import org.springframework.security.core.Authentication; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.AuthorityUtils; -import org.springframework.security.core.authority.GrantedAuthorityImpl; import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.web.util.ExpressionEvaluationUtils; - +import org.springframework.security.web.FilterInvocation; +import org.springframework.security.web.access.expression.WebSecurityExpressionHandler; +import org.springframework.web.context.support.WebApplicationContextUtils; /** - * An implementation of {@link javax.servlet.jsp.tagext.Tag} that allows it's body through if some authorizations - * are granted to the request's principal. + * Expression-based access control tag. * - * @author Francois Beausoleil + * @author Luke Taylor * @version $Id$ + * @since 3.0 */ -public class AuthorizeTag extends TagSupport { - //~ Instance fields ================================================================================================ - - private String ifAllGranted = ""; - private String ifAnyGranted = ""; - private String ifNotGranted = ""; - - //~ Methods ======================================================================================================== - - private Set authoritiesToRoles(Collection c) { - Set target = new HashSet(); - - for (GrantedAuthority authority : c) { - 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; - } +public class AuthorizeTag extends LegacyAuthorizeTag { + private String access; + // If access expression evaluates to "true" return public int doStartTag() throws JspException { - if (((null == ifAllGranted) || "".equals(ifAllGranted)) && ((null == ifAnyGranted) || "".equals(ifAnyGranted)) - && ((null == ifNotGranted) || "".equals(ifNotGranted))) { - return Tag.SKIP_BODY; + if (access == null || access.length() == 0) { + return super.doStartTag(); } - final Collection granted = getPrincipalAuthorities(); - - final String evaledIfNotGranted = ExpressionEvaluationUtils.evaluateString("ifNotGranted", ifNotGranted, - pageContext); - - if ((null != evaledIfNotGranted) && !"".equals(evaledIfNotGranted)) { - Set grantedCopy = retainAll(granted, parseAuthoritiesString(evaledIfNotGranted)); - - if (!grantedCopy.isEmpty()) { - return Tag.SKIP_BODY; - } - } - - final String evaledIfAllGranted = ExpressionEvaluationUtils.evaluateString("ifAllGranted", ifAllGranted, - pageContext); - - if ((null != evaledIfAllGranted) && !"".equals(evaledIfAllGranted)) { - if (!granted.containsAll(parseAuthoritiesString(evaledIfAllGranted))) { - return Tag.SKIP_BODY; - } - } - - final String evaledIfAnyGranted = ExpressionEvaluationUtils.evaluateString("ifAnyGranted", ifAnyGranted, - pageContext); - - if ((null != evaledIfAnyGranted) && !"".equals(evaledIfAnyGranted)) { - Set grantedCopy = retainAll(granted, parseAuthoritiesString(evaledIfAnyGranted)); - - if (grantedCopy.isEmpty()) { - return Tag.SKIP_BODY; - } - } - - return Tag.EVAL_BODY_INCLUDE; - } - - public String getIfAllGranted() { - return ifAllGranted; - } - - public String getIfAnyGranted() { - return ifAnyGranted; - } - - public String getIfNotGranted() { - return ifNotGranted; - } - - private Collection getPrincipalAuthorities() { Authentication currentUser = SecurityContextHolder.getContext().getAuthentication(); - if (null == currentUser) { - return Collections.emptyList(); + if (currentUser == null) { + return SKIP_BODY; } - if ((null == currentUser.getAuthorities())) { - return Collections.emptyList(); + // Get web expression + WebSecurityExpressionHandler handler = getExpressionHandler(); + + Expression accessExpression; + try { + accessExpression = handler.getExpressionParser().parseExpression(access); + + } catch (ParseException e) { + throw new JspException(e); } - return currentUser.getAuthorities(); - } + FilterInvocation f = new FilterInvocation(pageContext.getRequest(), pageContext.getResponse(), DUMMY_CHAIN); - private Set parseAuthoritiesString(String authorizationsString) { - final Set requiredAuthorities = new HashSet(); - requiredAuthorities.addAll(AuthorityUtils.commaSeparatedStringToAuthorityList(authorizationsString)); - - return requiredAuthorities; - } - - /** - * Find the common authorities between the current authentication's {@link GrantedAuthority} and the ones - * that have been specified in the tag's ifAny, ifNot or ifAllGranted attributes.

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.

- *

- * CAVEAT: This method will not work if the granted authorities - * returns a null string as the return value of {@link GrantedAuthority#getAuthority()}. - *

- * - * @param granted The authorities granted by the authentication. May be any implementation of {@link - * GrantedAuthority} that does not return null from {@link - * 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 granted and required. - * - */ - private Set retainAll(final Collection granted, final Set required) { - Set grantedRoles = authoritiesToRoles(granted); - Set requiredRoles = authoritiesToRoles(required); - grantedRoles.retainAll(requiredRoles); - - return rolesToAuthorities(grantedRoles, granted); - } - - private Set rolesToAuthorities(Set grantedRoles, Collection granted) { - Set target = new HashSet(); - - for (String role : grantedRoles) { - for (GrantedAuthority authority : granted) { - if (authority.getAuthority().equals(role)) { - target.add(authority); - - break; - } - } + if (ExpressionUtils.evaluateAsBoolean(accessExpression, handler.createEvaluationContext(currentUser, f))) { + return EVAL_BODY_INCLUDE; } - return target; + return SKIP_BODY; } - public void setIfAllGranted(String ifAllGranted) throws JspException { - this.ifAllGranted = ifAllGranted; + public void setAccess(String access) { + this.access = access; } - public void setIfAnyGranted(String ifAnyGranted) throws JspException { - this.ifAnyGranted = ifAnyGranted; + WebSecurityExpressionHandler getExpressionHandler() throws JspException { + ServletContext servletContext = pageContext.getServletContext(); + ApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext); + Map expressionHdlrs = ctx.getBeansOfType(WebSecurityExpressionHandler.class); + + if (expressionHdlrs.size() == 0) { + throw new JspException("No visible WebSecurityExpressionHandler instance could be found in the application " + + "context. There must be at least one in order to use expressions with taglib support."); + } + + return (WebSecurityExpressionHandler) expressionHdlrs.values().toArray()[0]; } - public void setIfNotGranted(String ifNotGranted) throws JspException { - this.ifNotGranted = ifNotGranted; - } + private static final FilterChain DUMMY_CHAIN = new FilterChain() { + public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { + throw new UnsupportedOperationException(); + } + }; } diff --git a/taglibs/src/main/java/org/springframework/security/taglibs/authz/LegacyAuthorizeTag.java b/taglibs/src/main/java/org/springframework/security/taglibs/authz/LegacyAuthorizeTag.java new file mode 100644 index 0000000000..725aa259f7 --- /dev/null +++ b/taglibs/src/main/java/org/springframework/security/taglibs/authz/LegacyAuthorizeTag.java @@ -0,0 +1,197 @@ +/* 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.taglibs.authz; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.Tag; +import javax.servlet.jsp.tagext.TagSupport; + +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.core.authority.GrantedAuthorityImpl; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.web.util.ExpressionEvaluationUtils; + + +/** + * An implementation of {@link javax.servlet.jsp.tagext.Tag} that allows it's body through if some authorizations + * are granted to the request's principal. + * + * @author Francois Beausoleil + * @version $Id$ + */ +public class LegacyAuthorizeTag extends TagSupport { + //~ Instance fields ================================================================================================ + + private String ifAllGranted = ""; + private String ifAnyGranted = ""; + private String ifNotGranted = ""; + + //~ Methods ======================================================================================================== + + private Set authoritiesToRoles(Collection c) { + Set target = new HashSet(); + + for (GrantedAuthority authority : c) { + 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; + } + + public int doStartTag() throws JspException { + if (((null == ifAllGranted) || "".equals(ifAllGranted)) && ((null == ifAnyGranted) || "".equals(ifAnyGranted)) + && ((null == ifNotGranted) || "".equals(ifNotGranted))) { + return Tag.SKIP_BODY; + } + + final Collection granted = getPrincipalAuthorities(); + + final String evaledIfNotGranted = ExpressionEvaluationUtils.evaluateString("ifNotGranted", ifNotGranted, + pageContext); + + if ((null != evaledIfNotGranted) && !"".equals(evaledIfNotGranted)) { + Set grantedCopy = retainAll(granted, parseAuthoritiesString(evaledIfNotGranted)); + + if (!grantedCopy.isEmpty()) { + return Tag.SKIP_BODY; + } + } + + final String evaledIfAllGranted = ExpressionEvaluationUtils.evaluateString("ifAllGranted", ifAllGranted, + pageContext); + + if ((null != evaledIfAllGranted) && !"".equals(evaledIfAllGranted)) { + if (!granted.containsAll(parseAuthoritiesString(evaledIfAllGranted))) { + return Tag.SKIP_BODY; + } + } + + final String evaledIfAnyGranted = ExpressionEvaluationUtils.evaluateString("ifAnyGranted", ifAnyGranted, + pageContext); + + if ((null != evaledIfAnyGranted) && !"".equals(evaledIfAnyGranted)) { + Set grantedCopy = retainAll(granted, parseAuthoritiesString(evaledIfAnyGranted)); + + if (grantedCopy.isEmpty()) { + return Tag.SKIP_BODY; + } + } + + return Tag.EVAL_BODY_INCLUDE; + } + + public String getIfAllGranted() { + return ifAllGranted; + } + + public String getIfAnyGranted() { + return ifAnyGranted; + } + + public String getIfNotGranted() { + return ifNotGranted; + } + + private Collection getPrincipalAuthorities() { + Authentication currentUser = SecurityContextHolder.getContext().getAuthentication(); + + if (null == currentUser) { + return Collections.emptyList(); + } + + if ((null == currentUser.getAuthorities())) { + return Collections.emptyList(); + } + + return currentUser.getAuthorities(); + } + + private Set parseAuthoritiesString(String authorizationsString) { + final Set requiredAuthorities = new HashSet(); + requiredAuthorities.addAll(AuthorityUtils.commaSeparatedStringToAuthorityList(authorizationsString)); + + return requiredAuthorities; + } + + /** + * Find the common authorities between the current authentication's {@link GrantedAuthority} and the ones + * that have been specified in the tag's ifAny, ifNot or ifAllGranted attributes.

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.

+ *

+ * CAVEAT: This method will not work if the granted authorities + * returns a null string as the return value of {@link GrantedAuthority#getAuthority()}. + *

+ * + * @param granted The authorities granted by the authentication. May be any implementation of {@link + * GrantedAuthority} that does not return null from {@link + * 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 granted and required. + * + */ + private Set retainAll(final Collection granted, final Set required) { + Set grantedRoles = authoritiesToRoles(granted); + Set requiredRoles = authoritiesToRoles(required); + grantedRoles.retainAll(requiredRoles); + + return rolesToAuthorities(grantedRoles, granted); + } + + private Set rolesToAuthorities(Set grantedRoles, Collection granted) { + Set target = new HashSet(); + + for (String role : grantedRoles) { + for (GrantedAuthority authority : granted) { + if (authority.getAuthority().equals(role)) { + target.add(authority); + + break; + } + } + } + + return target; + } + + public void setIfAllGranted(String ifAllGranted) throws JspException { + this.ifAllGranted = ifAllGranted; + } + + public void setIfAnyGranted(String ifAnyGranted) throws JspException { + this.ifAnyGranted = ifAnyGranted; + } + + public void setIfNotGranted(String ifNotGranted) throws JspException { + this.ifNotGranted = ifNotGranted; + } +} diff --git a/taglibs/src/main/java/org/springframework/security/taglibs/velocity/Authz.java b/taglibs/src/main/java/org/springframework/security/taglibs/velocity/Authz.java index 262729038a..7b35f3fe10 100644 --- a/taglibs/src/main/java/org/springframework/security/taglibs/velocity/Authz.java +++ b/taglibs/src/main/java/org/springframework/security/taglibs/velocity/Authz.java @@ -19,7 +19,7 @@ package org.springframework.security.taglibs.velocity; import org.springframework.security.core.Authentication; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.taglibs.authz.AuthenticationTag; -import org.springframework.security.taglibs.authz.AuthorizeTag; +import org.springframework.security.taglibs.authz.LegacyAuthorizeTag; import org.springframework.context.ApplicationContext; @@ -27,7 +27,7 @@ import org.springframework.context.ApplicationContext; /** * Wrapper the implementation of Spring Security JSP tag includes: - * {@link AuthenticationTag}, {@link AclTag}, {@link AuthorizeTag} + * {@link AuthenticationTag}, {@link AclTag}, {@link LegacyAuthorizeTag} * * @author Wang Qi * @version $Id$ diff --git a/taglibs/src/main/java/org/springframework/security/taglibs/velocity/AuthzImpl.java b/taglibs/src/main/java/org/springframework/security/taglibs/velocity/AuthzImpl.java index f146820c7b..b4de6121e5 100644 --- a/taglibs/src/main/java/org/springframework/security/taglibs/velocity/AuthzImpl.java +++ b/taglibs/src/main/java/org/springframework/security/taglibs/velocity/AuthzImpl.java @@ -20,7 +20,7 @@ import javax.servlet.jsp.tagext.Tag; import org.springframework.context.ApplicationContext; import org.springframework.security.taglibs.authz.AuthenticationTag; -import org.springframework.security.taglibs.authz.AuthorizeTag; +import org.springframework.security.taglibs.authz.LegacyAuthorizeTag; /** @@ -72,7 +72,7 @@ public class AuthzImpl implements Authz { } /** - * implementation of AuthorizeTag + * implementation of LegacyAuthorizeTag * * @param roles DOCUMENT ME! * @param grantType DOCUMENT ME! @@ -82,7 +82,7 @@ public class AuthzImpl implements Authz { * @throws IllegalArgumentException DOCUMENT ME! */ private boolean ifGranted(String roles, int grantType) { - AuthorizeTag authorizeTag = new AuthorizeTag(); + LegacyAuthorizeTag authorizeTag = new LegacyAuthorizeTag(); int result = -1; diff --git a/taglibs/src/main/resources/META-INF/security.tld b/taglibs/src/main/resources/META-INF/security.tld index c7c1f09489..d4683d7e0a 100644 --- a/taglibs/src/main/resources/META-INF/security.tld +++ b/taglibs/src/main/resources/META-INF/security.tld @@ -16,17 +16,27 @@ authorize org.springframework.security.taglibs.authz.AuthorizeTag - A simple tag to output or not the body of the tag if the principal - has or doesn't have certain authorities. + A tag which outputs the body of the tag if the configured access expression + evaluates to true for the currently authenticated principal. + + access + false + false + + A Spring-EL expression which is supported by the WebSecurityExpressionHandler + in the application context. The latter will be used to evaluate the expression. + + + ifNotGranted false true A comma separated list of roles which the user must not have - for the body to be output. + for the body to be output. Deprecated in favour of the access expression. @@ -36,7 +46,7 @@ true A comma separated list of roles which the user must all - possess for the body to be output. + possess for the body to be output. Deprecated in favour of the access expression. @@ -46,7 +56,7 @@ true A comma separated list of roles, one of which the user must - possess for the body to be output. + possess for the body to be output. Deprecated in favour of the access expression. diff --git a/taglibs/src/test/java/org/springframework/security/taglibs/authz/AuthorizeTagAttributeTests.java b/taglibs/src/test/java/org/springframework/security/taglibs/authz/AuthorizeTagAttributeTests.java index bafe0f8bda..6c67b53932 100644 --- a/taglibs/src/test/java/org/springframework/security/taglibs/authz/AuthorizeTagAttributeTests.java +++ b/taglibs/src/test/java/org/springframework/security/taglibs/authz/AuthorizeTagAttributeTests.java @@ -37,7 +37,7 @@ import javax.servlet.jsp.tagext.Tag; public class AuthorizeTagAttributeTests extends TestCase { //~ Instance fields ================================================================================================ - private final AuthorizeTag authorizeTag = new AuthorizeTag(); + private final LegacyAuthorizeTag authorizeTag = new LegacyAuthorizeTag(); private TestingAuthenticationToken currentUser; //~ Methods ======================================================================================================== diff --git a/taglibs/src/test/java/org/springframework/security/taglibs/authz/AuthorizeTagCustomGrantedAuthorityTests.java b/taglibs/src/test/java/org/springframework/security/taglibs/authz/AuthorizeTagCustomGrantedAuthorityTests.java index 4a8305d091..fb339121c0 100644 --- a/taglibs/src/test/java/org/springframework/security/taglibs/authz/AuthorizeTagCustomGrantedAuthorityTests.java +++ b/taglibs/src/test/java/org/springframework/security/taglibs/authz/AuthorizeTagCustomGrantedAuthorityTests.java @@ -35,7 +35,7 @@ import javax.servlet.jsp.tagext.Tag; public class AuthorizeTagCustomGrantedAuthorityTests extends TestCase { //~ Instance fields ================================================================================================ - private final AuthorizeTag authorizeTag = new AuthorizeTag(); + private final LegacyAuthorizeTag authorizeTag = new LegacyAuthorizeTag(); private TestingAuthenticationToken currentUser; //~ Methods ======================================================================================================== diff --git a/taglibs/src/test/java/org/springframework/security/taglibs/authz/AuthorizeTagExpressionLanguageTests.java b/taglibs/src/test/java/org/springframework/security/taglibs/authz/AuthorizeTagExpressionLanguageTests.java index bcff6f5dfe..f941a103b0 100644 --- a/taglibs/src/test/java/org/springframework/security/taglibs/authz/AuthorizeTagExpressionLanguageTests.java +++ b/taglibs/src/test/java/org/springframework/security/taglibs/authz/AuthorizeTagExpressionLanguageTests.java @@ -36,7 +36,7 @@ public class AuthorizeTagExpressionLanguageTests extends TestCase { Mockery jmock = new Mockery(); //~ Instance fields ================================================================================================ - private final AuthorizeTag authorizeTag = new AuthorizeTag(); + private final LegacyAuthorizeTag authorizeTag = new LegacyAuthorizeTag(); private MockPageContext pageContext; private TestingAuthenticationToken currentUser; diff --git a/taglibs/src/test/java/org/springframework/security/taglibs/authz/AuthorizeTagTests.java b/taglibs/src/test/java/org/springframework/security/taglibs/authz/AuthorizeTagTests.java index ed37e3568d..755c54b002 100644 --- a/taglibs/src/test/java/org/springframework/security/taglibs/authz/AuthorizeTagTests.java +++ b/taglibs/src/test/java/org/springframework/security/taglibs/authz/AuthorizeTagTests.java @@ -15,97 +15,131 @@ package org.springframework.security.taglibs.authz; -import junit.framework.TestCase; - - -import org.springframework.security.authentication.TestingAuthenticationToken; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.GrantedAuthorityImpl; -import org.springframework.security.core.context.SecurityContextHolder; - +import static org.junit.Assert.assertEquals; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.Tag; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.mock.web.MockPageContext; +import org.springframework.mock.web.MockServletContext; +import org.springframework.security.authentication.TestingAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.support.StaticWebApplicationContext; + /** - * DOCUMENT ME! - * * @author Francois Beausoleil * @version $Id$ */ -public class AuthorizeTagTests extends TestCase { +public class AuthorizeTagTests { //~ Instance fields ================================================================================================ - private final AuthorizeTag authorizeTag = new AuthorizeTag(); - private TestingAuthenticationToken currentUser; + private AuthorizeTag authorizeTag; + private final TestingAuthenticationToken currentUser = new TestingAuthenticationToken("abc", "123", "ROLE SUPERVISOR", "ROLE_TELLER"); //~ Methods ======================================================================================================== - protected void setUp() throws Exception { - super.setUp(); - - currentUser = new TestingAuthenticationToken("abc", "123", - new GrantedAuthority[] { - new GrantedAuthorityImpl("ROLE SUPERVISOR"), new GrantedAuthorityImpl("ROLE_TELLER"), - }); - + @Before + public void setUp() throws Exception { SecurityContextHolder.getContext().setAuthentication(currentUser); + StaticWebApplicationContext ctx = new StaticWebApplicationContext(); + ctx.registerSingleton("expressionHandler", DefaultWebSecurityExpressionHandler.class); + MockServletContext servletCtx = new MockServletContext(); + servletCtx.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ctx); + authorizeTag = new AuthorizeTag(); + authorizeTag.setPageContext(new MockPageContext(servletCtx, new MockHttpServletRequest(), new MockHttpServletResponse())); } - protected void tearDown() throws Exception { + @After + public void tearDown() throws Exception { SecurityContextHolder.clearContext(); } - public void testAlwaysReturnsUnauthorizedIfNoUserFound() throws JspException { - SecurityContextHolder.getContext().setAuthentication(null); + // access attribute tests - authorizeTag.setIfAllGranted("ROLE_TELLER"); - assertEquals("prevents request - no principal in Context", Tag.SKIP_BODY, authorizeTag.doStartTag()); + @Test + public void skipsBodyIfNoAuthenticationPresent() throws Exception { + SecurityContextHolder.clearContext(); + authorizeTag.setAccess("permitAll"); + assertEquals(Tag.SKIP_BODY, authorizeTag.doStartTag()); } + @Test + public void skipsBodyIfAccessExpressionDeniesAccess() throws Exception { + authorizeTag.setAccess("denyAll"); + assertEquals(Tag.SKIP_BODY, authorizeTag.doStartTag()); + } + + @Test + public void showsBodyIfAccessExpressionAllowsAccess() throws Exception { + authorizeTag.setAccess("permitAll"); + assertEquals(Tag.EVAL_BODY_INCLUDE, authorizeTag.doStartTag()); + } + // Legacy attribute tests + + @Test + public void testAlwaysReturnsUnauthorizedIfNoUserFound() throws JspException { + SecurityContextHolder.clearContext(); + authorizeTag.setIfAllGranted("ROLE_TELLER"); + assertEquals(Tag.SKIP_BODY, authorizeTag.doStartTag()); + } + + @Test public void testDefaultsToNotOutputtingBodyWhenNoRequiredAuthorities() throws JspException { assertEquals("", authorizeTag.getIfAllGranted()); assertEquals("", authorizeTag.getIfAnyGranted()); assertEquals("", authorizeTag.getIfNotGranted()); - assertEquals("prevents body output - no authorities granted", Tag.SKIP_BODY, authorizeTag.doStartTag()); + assertEquals(Tag.SKIP_BODY, authorizeTag.doStartTag()); } + @Test public void testOutputsBodyIfOneRolePresent() throws JspException { authorizeTag.setIfAnyGranted("ROLE_TELLER"); - assertEquals("authorized - ROLE_TELLER in both sets", Tag.EVAL_BODY_INCLUDE, authorizeTag.doStartTag()); + assertEquals(Tag.EVAL_BODY_INCLUDE, authorizeTag.doStartTag()); } + @Test public void testOutputsBodyWhenAllGranted() throws JspException { authorizeTag.setIfAllGranted("ROLE SUPERVISOR, \nROLE_TELLER"); - assertEquals("allows request - all required roles granted on principal", Tag.EVAL_BODY_INCLUDE, - authorizeTag.doStartTag()); + assertEquals(Tag.EVAL_BODY_INCLUDE, authorizeTag.doStartTag()); } + @Test public void testOutputsBodyWhenNotGrantedSatisfied() throws JspException { authorizeTag.setIfNotGranted("ROLE_BANKER"); - assertEquals("allows request - principal doesn't have ROLE_BANKER", Tag.EVAL_BODY_INCLUDE, + assertEquals(Tag.EVAL_BODY_INCLUDE, authorizeTag.doStartTag()); } + @Test public void testPreventsBodyOutputIfNoSecurityContext() throws JspException { SecurityContextHolder.getContext().setAuthentication(null); authorizeTag.setIfAnyGranted("ROLE_BANKER"); - assertEquals("prevents output - no context defined", Tag.SKIP_BODY, authorizeTag.doStartTag()); + assertEquals(Tag.SKIP_BODY, authorizeTag.doStartTag()); } + @Test public void testSkipsBodyIfNoAnyRolePresent() throws JspException { authorizeTag.setIfAnyGranted("ROLE_BANKER"); - assertEquals("unauthorized - ROLE_BANKER not in granted authorities", Tag.SKIP_BODY, authorizeTag.doStartTag()); + assertEquals(Tag.SKIP_BODY, authorizeTag.doStartTag()); } + @Test public void testSkipsBodyWhenMissingAnAllGranted() throws JspException { authorizeTag.setIfAllGranted("ROLE SUPERVISOR, ROLE_TELLER,\n\rROLE_BANKER"); - assertEquals("prevents request - missing ROLE_BANKER on principal", Tag.SKIP_BODY, authorizeTag.doStartTag()); + assertEquals(Tag.SKIP_BODY, authorizeTag.doStartTag()); } + @Test public void testSkipsBodyWhenNotGrantedUnsatisfied() throws JspException { authorizeTag.setIfNotGranted("ROLE_TELLER"); assertEquals("prevents request - principal has ROLE_TELLER", Tag.SKIP_BODY, authorizeTag.doStartTag());