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.Authentication;
|
||||||
import net.sf.acegisecurity.UserDetails;
|
import net.sf.acegisecurity.UserDetails;
|
||||||
|
import net.sf.acegisecurity.context.SecurityContext;
|
||||||
import net.sf.acegisecurity.context.SecurityContextHolder;
|
import net.sf.acegisecurity.context.SecurityContextHolder;
|
||||||
|
|
||||||
import java.io.IOException;
|
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.JspException;
|
||||||
import javax.servlet.jsp.tagext.Tag;
|
import javax.servlet.jsp.tagext.Tag;
|
||||||
import javax.servlet.jsp.tagext.TagSupport;
|
import javax.servlet.jsp.tagext.TagSupport;
|
||||||
|
@ -43,14 +50,28 @@ import javax.servlet.jsp.tagext.TagSupport;
|
||||||
public class AuthenticationTag extends TagSupport {
|
public class AuthenticationTag extends TagSupport {
|
||||||
//~ Static fields/initializers =============================================
|
//~ 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 ========================================================
|
//~ Instance fields ========================================================
|
||||||
|
|
||||||
|
private String methodPrefix = "get";
|
||||||
private String operation = "";
|
private String operation = "";
|
||||||
|
|
||||||
//~ Methods ================================================================
|
//~ Methods ================================================================
|
||||||
|
|
||||||
|
public void setMethodPrefix(String methodPrefix) {
|
||||||
|
this.methodPrefix = methodPrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMethodPrefix() {
|
||||||
|
return methodPrefix;
|
||||||
|
}
|
||||||
|
|
||||||
public void setOperation(String operation) {
|
public void setOperation(String operation) {
|
||||||
this.operation = operation;
|
this.operation = operation;
|
||||||
}
|
}
|
||||||
|
@ -64,11 +85,12 @@ public class AuthenticationTag extends TagSupport {
|
||||||
return Tag.SKIP_BODY;
|
return Tag.SKIP_BODY;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!OPERATION_PRINCIPAL.equalsIgnoreCase(operation)) {
|
validateArguments();
|
||||||
throw new JspException("Unsupported use of auth:authentication tag");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SecurityContextHolder.getContext().getAuthentication() == null) {
|
if ((SecurityContextHolder.getContext() == null)
|
||||||
|
|| !(SecurityContextHolder.getContext() instanceof SecurityContext)
|
||||||
|
|| (((SecurityContext) SecurityContextHolder.getContext())
|
||||||
|
.getAuthentication() == null)) {
|
||||||
return Tag.SKIP_BODY;
|
return Tag.SKIP_BODY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +100,7 @@ public class AuthenticationTag extends TagSupport {
|
||||||
if (auth.getPrincipal() == null) {
|
if (auth.getPrincipal() == null) {
|
||||||
return Tag.SKIP_BODY;
|
return Tag.SKIP_BODY;
|
||||||
} else if (auth.getPrincipal() instanceof UserDetails) {
|
} else if (auth.getPrincipal() instanceof UserDetails) {
|
||||||
writeMessage(((UserDetails) auth.getPrincipal()).getUsername());
|
writeMessage(invokeOperation(auth.getPrincipal()));
|
||||||
|
|
||||||
return Tag.SKIP_BODY;
|
return Tag.SKIP_BODY;
|
||||||
} else {
|
} 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 {
|
protected void writeMessage(String msg) throws JspException {
|
||||||
try {
|
try {
|
||||||
pageContext.getOut().write(String.valueOf(msg));
|
pageContext.getOut().write(String.valueOf(msg));
|
||||||
|
|
|
@ -63,10 +63,21 @@
|
||||||
<required>true</required>
|
<required>true</required>
|
||||||
<rtexprvalue>true</rtexprvalue>
|
<rtexprvalue>true</rtexprvalue>
|
||||||
<description>
|
<description>
|
||||||
Must be "principal", for a String representation of the
|
Must be one of the methods of an instance that implements the UserDetails
|
||||||
username. An attribute to aid in future extension of the tag.
|
interface. Use the JavaBean style property, you can provide a custom prefix
|
||||||
|
for the method to call.
|
||||||
</description>
|
</description>
|
||||||
</attribute>
|
</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>
|
</tag>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,20 @@ public class AuthenticationTagTests extends TestCase {
|
||||||
|
|
||||||
//~ Methods ================================================================
|
//~ 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 {
|
public void testOperationWhenPrincipalIsAString() throws JspException {
|
||||||
Authentication auth = new TestingAuthenticationToken("marissaAsString",
|
Authentication auth = new TestingAuthenticationToken("marissaAsString",
|
||||||
"koala", new GrantedAuthority[] {});
|
"koala", new GrantedAuthority[] {});
|
||||||
|
@ -58,7 +72,7 @@ public class AuthenticationTagTests extends TestCase {
|
||||||
new GrantedAuthority[] {});
|
new GrantedAuthority[] {});
|
||||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||||
|
|
||||||
authenticationTag.setOperation("principal");
|
authenticationTag.setOperation("username");
|
||||||
assertEquals(Tag.SKIP_BODY, authenticationTag.doStartTag());
|
assertEquals(Tag.SKIP_BODY, authenticationTag.doStartTag());
|
||||||
assertEquals("marissaUserDetails", authenticationTag.getLastMessage());
|
assertEquals("marissaUserDetails", authenticationTag.getLastMessage());
|
||||||
}
|
}
|
||||||
|
@ -89,7 +103,29 @@ public class AuthenticationTagTests extends TestCase {
|
||||||
assertEquals(Tag.SKIP_BODY, authenticationTag.doStartTag());
|
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() {
|
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");
|
authenticationTag.setOperation("qsq");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
Loading…
Reference in New Issue