diff --git a/core/src/test/java/org/springframework/security/core/userdetails/memory/UserMapTests.java b/core/src/test/java/org/springframework/security/core/userdetails/memory/UserMapTests.java
index 08213b761e..581c1db957 100644
--- a/core/src/test/java/org/springframework/security/core/userdetails/memory/UserMapTests.java
+++ b/core/src/test/java/org/springframework/security/core/userdetails/memory/UserMapTests.java
@@ -15,8 +15,10 @@
package org.springframework.security.core.userdetails.memory;
+import static org.junit.Assert.*;
import junit.framework.TestCase;
+import org.junit.Test;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
@@ -29,9 +31,9 @@ import org.springframework.security.core.userdetails.memory.UserMap;
*
* @author Ben Alex
*/
-public class UserMapTests extends TestCase {
+public class UserMapTests {
- //~ Methods ========================================================================================================
+ @Test
public void testAddAndRetrieveUser() {
UserDetails rod = new User("rod", "koala", true, true, true, true,
AuthorityUtils.createAuthorityList("ROLE_ONE","ROLE_TWO"));
@@ -50,7 +52,8 @@ public class UserMapTests extends TestCase {
assertEquals(peter, map.getUser("peter"));
}
- public void testNullUserCannotBeAdded() {
+ @Test
+ public void nullUserCannotBeAdded() {
UserMap map = new UserMap();
assertEquals(0, map.getUserCount());
@@ -62,7 +65,8 @@ public class UserMapTests extends TestCase {
}
}
- public void testUnknownUserIsNotRetrieved() {
+ @Test
+ public void unknownUserIsNotRetrieved() {
UserDetails rod = new User("rod", "koala", true, true, true, true,
AuthorityUtils.createAuthorityList("ROLE_ONE","ROLE_TWO"));
UserMap map = new UserMap();
diff --git a/itest/web/src/main/webapp/WEB-INF/in-memory-provider.xml b/itest/web/src/main/webapp/WEB-INF/in-memory-provider.xml
index 83096639be..1f08e2c585 100644
--- a/itest/web/src/main/webapp/WEB-INF/in-memory-provider.xml
+++ b/itest/web/src/main/webapp/WEB-INF/in-memory-provider.xml
@@ -12,6 +12,7 @@
+
diff --git a/itest/web/src/main/webapp/WEB-INF/security.tld b/itest/web/src/main/webapp/WEB-INF/security.tld
new file mode 100644
index 0000000000..78ce820d1e
--- /dev/null
+++ b/itest/web/src/main/webapp/WEB-INF/security.tld
@@ -0,0 +1,158 @@
+
+
+
+ 1.0
+ 1.2
+ security
+ http://www.springframework.org/security/tags
+
+ Spring Security Authorization Tag Library
+ $Id$
+
+
+
+ authorize
+ org.springframework.security.taglibs.authz.AuthorizeTag
+
+ 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.
+
+
+
+
+ url
+ false
+ false
+
+ A URL within the application. If the user has access to this URL (as determined by
+ the AccessDecisionManager), the tag body will be evaluated. If not, it will
+ be skipped.
+
+
+
+
+ method
+ false
+ false
+
+ Can optionally be used to narrow down the HTTP method (typically GET or POST) to which the URL
+ applies to. Only has any meaning when used in combination with the "url" attribute.
+
+
+
+
+
+ ifNotGranted
+ false
+ true
+
+ A comma separated list of roles which the user must not have
+ for the body to be output. Deprecated in favour of the access expression.
+
+
+
+
+ ifAllGranted
+ false
+ true
+
+ A comma separated list of roles which the user must all
+ possess for the body to be output. Deprecated in favour of the access expression.
+
+
+
+
+ ifAnyGranted
+ false
+ true
+
+ A comma separated list of roles, one of which the user must
+ possess for the body to be output. Deprecated in favour of the access expression.
+
+
+
+
+
+ authentication
+ org.springframework.security.taglibs.authz.AuthenticationTag
+
+ Allows access to the current Authentication object.
+
+
+
+ property
+ true
+ true
+
+ Property of the Authentication object which should be output. Supports nested
+ properties. For example if the principal object is an instance of UserDetails,
+ the property "principal.username" will return the username. Alternatively, using
+ "name" will call getName method on the Authentication object directly.
+
+
+
+ var
+ false
+ false
+
+ Name of the exported scoped variable which will contain the
+ evaluated property of the Authentication object.
+
+
+
+ Set HTML escaping for this tag, as a boolean value.
+ htmlEscape
+ false
+ true
+
+
+ scope
+ false
+ false
+
+ Scope for var.
+
+
+
+
+
+ accesscontrollist
+ org.springframework.security.taglibs.authz.AccessControlListTag
+
+ Allows inclusion of a tag body if the current Authentication
+ has one of the specified permissions to the presented
+ domain object instance.
+
+
+
+ hasPermission
+ true
+ true
+
+ A comma separated list of permissions, which will be converted to
+ Permission instances by the configured PermissionFactory.
+
+
+
+ domainObject
+ true
+ true
+
+ The actual domain object instance for which permissions
+ are being evaluated.
+
+
+
+
+
diff --git a/itest/web/src/test/java/org/springframework/security/integration/InMemoryProviderWebAppTests.java b/itest/web/src/test/java/org/springframework/security/integration/InMemoryProviderWebAppTests.java
index bbeaab393a..7d6311008b 100644
--- a/itest/web/src/test/java/org/springframework/security/integration/InMemoryProviderWebAppTests.java
+++ b/itest/web/src/test/java/org/springframework/security/integration/InMemoryProviderWebAppTests.java
@@ -95,4 +95,16 @@ public class InMemoryProviderWebAppTests extends AbstractWebServerIntegrationTes
tester.assertTextPresent("This session has been expired");
}
+ @Test
+ public void authenticationTagEscapingWorksCorrectly() {
+ beginAt("secure/authenticationTagTestPage.jsp");
+ login("theescapist<>&.", "theescapistspassword");
+ String response = tester.getServerResponse();
+ assertTrue(response.contains("This is the unescaped authentication name: theescapist<>&."));
+ assertTrue(response.contains("This is the unescaped principal.username: theescapist<>&."));
+ assertTrue(response.contains("This is the authentication name: theescapist<>&."));
+ assertTrue(response.contains("This is the principal.username: theescapist<>&."));
+ }
+
+
}
diff --git a/taglibs/src/main/java/org/springframework/security/taglibs/authz/AuthenticationTag.java b/taglibs/src/main/java/org/springframework/security/taglibs/authz/AuthenticationTag.java
index efe8f5ca3a..04a286be29 100644
--- a/taglibs/src/main/java/org/springframework/security/taglibs/authz/AuthenticationTag.java
+++ b/taglibs/src/main/java/org/springframework/security/taglibs/authz/AuthenticationTag.java
@@ -23,6 +23,7 @@ import org.springframework.security.web.util.TextEscapeUtils;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.BeansException;
+import org.springframework.web.util.ExpressionEvaluationUtils;
import org.springframework.web.util.TagUtils;
import java.io.IOException;
@@ -48,6 +49,7 @@ public class AuthenticationTag extends TagSupport {
private String property;
private int scope;
private boolean scopeSpecified;
+ private boolean htmlEscape = true;
//~ Methods ========================================================================================================
@@ -120,7 +122,11 @@ public class AuthenticationTag extends TagSupport {
}
}
} else {
- writeMessage(TextEscapeUtils.escapeEntities(String.valueOf(result)));
+ if (htmlEscape) {
+ writeMessage(TextEscapeUtils.escapeEntities(String.valueOf(result)));
+ } else {
+ writeMessage(String.valueOf(result));
+ }
}
return EVAL_PAGE;
}
@@ -132,4 +138,21 @@ public class AuthenticationTag extends TagSupport {
throw new JspException(ioe);
}
}
+
+
+ /**
+ * Set HTML escaping for this tag, as boolean value.
+ */
+ public void setHtmlEscape(String htmlEscape) throws JspException {
+ this.htmlEscape = ExpressionEvaluationUtils.evaluateBoolean("htmlEscape", htmlEscape, pageContext);
+ }
+
+ /**
+ * Return the HTML escaping setting for this tag,
+ * or the default setting if not overridden.
+ * @see #isDefaultHtmlEscape()
+ */
+ protected boolean isHtmlEscape() {
+ return htmlEscape;
+ }
}
diff --git a/taglibs/src/main/resources/META-INF/security.tld b/taglibs/src/main/resources/META-INF/security.tld
index 410ee656be..78ce820d1e 100644
--- a/taglibs/src/main/resources/META-INF/security.tld
+++ b/taglibs/src/main/resources/META-INF/security.tld
@@ -110,6 +110,12 @@
evaluated property of the Authentication object.
+
+ Set HTML escaping for this tag, as a boolean value.
+ htmlEscape
+ false
+ true
+
scope
false
diff --git a/taglibs/src/test/java/org/springframework/security/taglibs/authz/AuthenticationTagTests.java b/taglibs/src/test/java/org/springframework/security/taglibs/authz/AuthenticationTagTests.java
index 201a27ceb3..518a4ba188 100644
--- a/taglibs/src/test/java/org/springframework/security/taglibs/authz/AuthenticationTagTests.java
+++ b/taglibs/src/test/java/org/springframework/security/taglibs/authz/AuthenticationTagTests.java
@@ -15,11 +15,13 @@
package org.springframework.security.taglibs.authz;
+import static org.junit.Assert.*;
+
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.Tag;
-import junit.framework.TestCase;
-
+import org.junit.After;
+import org.junit.Test;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.AuthorityUtils;
@@ -32,7 +34,7 @@ import org.springframework.security.core.userdetails.User;
*
* @author Ben Alex
*/
-public class AuthenticationTagTests extends TestCase {
+public class AuthenticationTagTests {
//~ Instance fields ================================================================================================
private final MyAuthenticationTag authenticationTag = new MyAuthenticationTag();
@@ -41,10 +43,12 @@ public class AuthenticationTagTests extends TestCase {
//~ Methods ========================================================================================================
- protected void tearDown() throws Exception {
+ @After
+ public void tearDown() {
SecurityContextHolder.clearContext();
}
+ @Test
public void testOperationWhenPrincipalIsAUserDetailsInstance()throws JspException {
SecurityContextHolder.getContext().setAuthentication(auth);
@@ -54,6 +58,7 @@ public class AuthenticationTagTests extends TestCase {
assertEquals("rodUserDetails", authenticationTag.getLastMessage());
}
+ @Test
public void testOperationWhenPrincipalIsAString() throws JspException {
SecurityContextHolder.getContext().setAuthentication(
new TestingAuthenticationToken("rodAsString", "koala", AuthorityUtils.NO_AUTHORITIES ));
@@ -64,6 +69,7 @@ public class AuthenticationTagTests extends TestCase {
assertEquals("rodAsString", authenticationTag.getLastMessage());
}
+ @Test
public void testNestedPropertyIsReadCorrectly() throws JspException {
SecurityContextHolder.getContext().setAuthentication(auth);
@@ -73,6 +79,7 @@ public class AuthenticationTagTests extends TestCase {
assertEquals("rodUserDetails", authenticationTag.getLastMessage());
}
+ @Test
public void testOperationWhenPrincipalIsNull() throws JspException {
SecurityContextHolder.getContext().setAuthentication(
new TestingAuthenticationToken(null, "koala", AuthorityUtils.NO_AUTHORITIES ));
@@ -82,6 +89,7 @@ public class AuthenticationTagTests extends TestCase {
assertEquals(Tag.EVAL_PAGE, authenticationTag.doEndTag());
}
+ @Test
public void testOperationWhenSecurityContextIsNull() throws Exception {
SecurityContextHolder.getContext().setAuthentication(null);
@@ -91,12 +99,14 @@ public class AuthenticationTagTests extends TestCase {
assertEquals(null, authenticationTag.getLastMessage());
}
+ @Test
public void testSkipsBodyIfNullOrEmptyOperation() throws Exception {
authenticationTag.setProperty("");
assertEquals(Tag.SKIP_BODY, authenticationTag.doStartTag());
assertEquals(Tag.EVAL_PAGE, authenticationTag.doEndTag());
}
+ @Test
public void testThrowsExceptionForUnrecognisedProperty() {
SecurityContextHolder.getContext().setAuthentication(auth);
authenticationTag.setProperty("qsq");
@@ -109,6 +119,25 @@ public class AuthenticationTagTests extends TestCase {
}
}
+ @Test
+ public void htmlEscapingIsUsedByDefault() throws Exception {
+ SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("<>& ", ""));
+ authenticationTag.setProperty("name");
+ authenticationTag.doStartTag();
+ authenticationTag.doEndTag();
+ assertEquals("<>& ", authenticationTag.getLastMessage());
+ }
+
+ @Test
+ public void settingHtmlEscapeToFalsePreventsEscaping() throws Exception {
+ SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("<>& ", ""));
+ authenticationTag.setProperty("name");
+ authenticationTag.setHtmlEscape("false");
+ authenticationTag.doStartTag();
+ authenticationTag.doEndTag();
+ assertEquals("<>& ", authenticationTag.getLastMessage());
+ }
+
//~ Inner Classes ==================================================================================================
private class MyAuthenticationTag extends AuthenticationTag {