SEC-67: Enhance taglib to allow retrieval of custom UserDetails methods.
This commit is contained in:
parent
31a1f0be1a
commit
9be82a3d8f
|
@ -17,10 +17,17 @@ package net.sf.acegisecurity.taglibs.authz;
|
|||
|
||||
import net.sf.acegisecurity.Authentication;
|
||||
import net.sf.acegisecurity.UserDetails;
|
||||
import net.sf.acegisecurity.context.SecurityContext;
|
||||
import net.sf.acegisecurity.context.SecurityContextHolder;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
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;
|
||||
|
@ -43,14 +50,28 @@ import javax.servlet.jsp.tagext.TagSupport;
|
|||
public class AuthenticationTag extends TagSupport {
|
||||
//~ Static fields/initializers =============================================
|
||||
|
||||
public static final String OPERATION_PRINCIPAL = "principal";
|
||||
private final static Set methodPrefixValidOptions = new HashSet();
|
||||
|
||||
static {
|
||||
methodPrefixValidOptions.add("get");
|
||||
methodPrefixValidOptions.add("is");
|
||||
}
|
||||
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private String methodPrefix = "get";
|
||||
private String operation = "";
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public void setMethodPrefix(String methodPrefix) {
|
||||
this.methodPrefix = methodPrefix;
|
||||
}
|
||||
|
||||
public String getMethodPrefix() {
|
||||
return methodPrefix;
|
||||
}
|
||||
|
||||
public void setOperation(String operation) {
|
||||
this.operation = operation;
|
||||
}
|
||||
|
@ -64,11 +85,12 @@ public class AuthenticationTag extends TagSupport {
|
|||
return Tag.SKIP_BODY;
|
||||
}
|
||||
|
||||
if (!OPERATION_PRINCIPAL.equalsIgnoreCase(operation)) {
|
||||
throw new JspException("Unsupported use of auth:authentication tag");
|
||||
}
|
||||
validateArguments();
|
||||
|
||||
if (SecurityContextHolder.getContext().getAuthentication() == null) {
|
||||
if ((SecurityContextHolder.getContext() == null)
|
||||
|| !(SecurityContextHolder.getContext() instanceof SecurityContext)
|
||||
|| (((SecurityContext) SecurityContextHolder.getContext())
|
||||
.getAuthentication() == null)) {
|
||||
return Tag.SKIP_BODY;
|
||||
}
|
||||
|
||||
|
@ -78,7 +100,7 @@ public class AuthenticationTag extends TagSupport {
|
|||
if (auth.getPrincipal() == null) {
|
||||
return Tag.SKIP_BODY;
|
||||
} else if (auth.getPrincipal() instanceof UserDetails) {
|
||||
writeMessage(((UserDetails) auth.getPrincipal()).getUsername());
|
||||
writeMessage(invokeOperation(auth.getPrincipal()));
|
||||
|
||||
return Tag.SKIP_BODY;
|
||||
} else {
|
||||
|
@ -88,6 +110,55 @@ public class AuthenticationTag extends TagSupport {
|
|||
}
|
||||
}
|
||||
|
||||
protected String invokeOperation(Object obj) throws JspException {
|
||||
Class clazz = obj.getClass();
|
||||
String methodToInvoke = getOperation();
|
||||
StringBuffer methodName = new StringBuffer();
|
||||
methodName.append(getMethodPrefix());
|
||||
methodName.append(methodToInvoke.substring(0, 1).toUpperCase());
|
||||
methodName.append(methodToInvoke.substring(1));
|
||||
|
||||
Method method = null;
|
||||
|
||||
try {
|
||||
method = clazz.getDeclaredMethod(methodName.toString(), null);
|
||||
} catch (SecurityException se) {
|
||||
throw new JspException(se);
|
||||
} catch (NoSuchMethodException nsme) {
|
||||
throw new JspException(nsme);
|
||||
}
|
||||
|
||||
Object retVal = null;
|
||||
|
||||
try {
|
||||
retVal = method.invoke(obj, null);
|
||||
} catch (IllegalArgumentException iae) {
|
||||
throw new JspException(iae);
|
||||
} catch (IllegalAccessException iae) {
|
||||
throw new JspException(iae);
|
||||
} catch (InvocationTargetException ite) {
|
||||
throw new JspException(ite);
|
||||
}
|
||||
|
||||
if (retVal == null) {
|
||||
retVal = "";
|
||||
}
|
||||
|
||||
return retVal.toString();
|
||||
}
|
||||
|
||||
protected void validateArguments() throws JspException {
|
||||
if ((getMethodPrefix() != null) && !getMethodPrefix().equals("")) {
|
||||
if (!methodPrefixValidOptions.contains(getMethodPrefix())) {
|
||||
throw new JspException(
|
||||
"Authorization tag : no valid method prefix available");
|
||||
}
|
||||
} else {
|
||||
throw new JspException(
|
||||
"Authorization tag : no method prefix available");
|
||||
}
|
||||
}
|
||||
|
||||
protected void writeMessage(String msg) throws JspException {
|
||||
try {
|
||||
pageContext.getOut().write(String.valueOf(msg));
|
||||
|
|
|
@ -63,8 +63,19 @@
|
|||
<required>true</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
<description>
|
||||
Must be "principal", for a String representation of the
|
||||
username. An attribute to aid in future extension of the tag.
|
||||
Must be one of the methods of an instance that implements the UserDetails
|
||||
interface. Use the JavaBean style property, you can provide a custom prefix
|
||||
for the method to call.
|
||||
</description>
|
||||
</attribute>
|
||||
|
||||
<attribute>
|
||||
<name>methodPrefix</name>
|
||||
<required>false</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
<description>
|
||||
Must be get or is. This is used to determine the name of the
|
||||
method to be called. The default is get.
|
||||
</description>
|
||||
</attribute>
|
||||
</tag>
|
||||
|
|
|
@ -40,6 +40,20 @@ public class AuthenticationTagTests extends TestCase {
|
|||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public void testOperationAndMethodPrefixWhenPrincipalIsAUserDetailsInstance()
|
||||
throws JspException {
|
||||
Authentication auth = new TestingAuthenticationToken(new User(
|
||||
"marissaUserDetails", "koala", true, true, true, true,
|
||||
new GrantedAuthority[] {}), "koala",
|
||||
new GrantedAuthority[] {});
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
|
||||
authenticationTag.setOperation("username");
|
||||
authenticationTag.setMethodPrefix("get");
|
||||
assertEquals(Tag.SKIP_BODY, authenticationTag.doStartTag());
|
||||
assertEquals("marissaUserDetails", authenticationTag.getLastMessage());
|
||||
}
|
||||
|
||||
public void testOperationWhenPrincipalIsAString() throws JspException {
|
||||
Authentication auth = new TestingAuthenticationToken("marissaAsString",
|
||||
"koala", new GrantedAuthority[] {});
|
||||
|
@ -58,7 +72,7 @@ public class AuthenticationTagTests extends TestCase {
|
|||
new GrantedAuthority[] {});
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
|
||||
authenticationTag.setOperation("principal");
|
||||
authenticationTag.setOperation("username");
|
||||
assertEquals(Tag.SKIP_BODY, authenticationTag.doStartTag());
|
||||
assertEquals("marissaUserDetails", authenticationTag.getLastMessage());
|
||||
}
|
||||
|
@ -89,7 +103,29 @@ public class AuthenticationTagTests extends TestCase {
|
|||
assertEquals(Tag.SKIP_BODY, authenticationTag.doStartTag());
|
||||
}
|
||||
|
||||
public void testThrowsExceptionForUnrecognisedMethodPrefix() {
|
||||
Authentication auth = new TestingAuthenticationToken(new User(
|
||||
"marissaUserDetails", "koala", true, true, true, true,
|
||||
new GrantedAuthority[] {}), "koala",
|
||||
new GrantedAuthority[] {});
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
authenticationTag.setOperation("username");
|
||||
authenticationTag.setMethodPrefix("qrq");
|
||||
|
||||
try {
|
||||
authenticationTag.doStartTag();
|
||||
fail("Should have thrown a JspException");
|
||||
} catch (JspException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testThrowsExceptionForUnrecognisedOperation() {
|
||||
Authentication auth = new TestingAuthenticationToken(new User(
|
||||
"marissaUserDetails", "koala", true, true, true, true,
|
||||
new GrantedAuthority[] {}), "koala",
|
||||
new GrantedAuthority[] {});
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
authenticationTag.setOperation("qsq");
|
||||
|
||||
try {
|
||||
|
|
Loading…
Reference in New Issue