Ver código fonte

SEC-58: Initial commit of Velocity helper.

Ben Alex 20 anos atrás
pai
commit
75a9784028

+ 112 - 0
core/src/main/java/org/acegisecurity/taglibs/velocity/Authz.java

@@ -0,0 +1,112 @@
+/* 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 org.acegisecurity.taglibs.velocity;
+
+import org.acegisecurity.Authentication;
+
+import org.acegisecurity.acl.AclManager;
+
+import org.acegisecurity.taglibs.authz.AclTag;
+import org.acegisecurity.taglibs.authz.AuthenticationTag;
+import org.acegisecurity.taglibs.authz.AuthorizeTag;
+
+import org.acegisecurity.userdetails.UserDetails;
+
+import org.springframework.context.ApplicationContext;
+
+
+/**
+ * Wrapper the implementation of Acegi Security for Spring JSP tag includes:
+ * {@link AuthenticationTag}, {@link AclTag}, {@link AuthorizeTag}
+ *
+ * @author Wang Qi
+ * @version $Id$
+ */
+public interface Authz {
+    //~ Methods ================================================================
+
+    /**
+     * all the listed roles must be granted to return true, otherwise fasle;
+     *
+     * @param roles - comma separate GrantedAuthoritys
+     *
+     * @return granted (true|false)
+     */
+    public boolean allGranted(String roles);
+
+    /**
+     * any the listed roles must be granted to return true, otherwise fasle;
+     *
+     * @param roles - comma separate GrantedAuthoritys
+     *
+     * @return granted (true|false)
+     */
+    public boolean anyGranted(String roles);
+
+    /**
+     * set Spring application context which contains acegi related bean
+     *
+     * @return DOCUMENT ME!
+     */
+    public ApplicationContext getAppCtx();
+
+    /**
+     * return the principal's name, supports the various type of principals
+     * that can exist in the {@link Authentication} object, such as a String
+     * or {@link UserDetails} instance
+     *
+     * @return string representation of principal's name
+     */
+    public String getPrincipal();
+
+    /**
+     * return true if the principal holds either permission specified for the
+     * provided domain object
+     * 
+     * <P>
+     * Only works with permissions that are subclasses of {@link
+     * net.sf.acegisecurity.acl.basic.AbstractBasicAclEntry}.
+     * </p>
+     * 
+     * <p>
+     * For this class to operate it must be able to access the application
+     * context via the <code>WebApplicationContextUtils</code> and locate an
+     * {@link AclManager}.
+     * </p>
+     *
+     * @param domainObject - domain object need acl control
+     * @param permissions - comma separate integer permissions
+     *
+     * @return got acl permission (true|false)
+     */
+    public boolean hasPermission(Object domainObject, String permissions);
+
+    /**
+     * none the listed roles must be granted to return true, otherwise fasle;
+     *
+     * @param roles - comma separate GrantedAuthoritys
+     *
+     * @return granted (true|false)
+     */
+    public boolean noneGranted(String roles);
+
+    /**
+     * get Spring application context which contains acegi related bean
+     *
+     * @param appCtx DOCUMENT ME!
+     */
+    public void setAppCtx(ApplicationContext appCtx);
+}

+ 217 - 0
core/src/main/java/org/acegisecurity/taglibs/velocity/AuthzImpl.java

@@ -0,0 +1,217 @@
+/* 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 org.acegisecurity.taglibs.velocity;
+
+import org.acegisecurity.acl.AclManager;
+
+import org.acegisecurity.taglibs.authz.AclTag;
+import org.acegisecurity.taglibs.authz.AuthenticationTag;
+import org.acegisecurity.taglibs.authz.AuthorizeTag;
+
+import org.springframework.context.ApplicationContext;
+
+import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.PageContext;
+import javax.servlet.jsp.tagext.Tag;
+
+
+/**
+ * I decided to wrap several JSP tag in one class, so I have to using inner
+ * class to wrap these JSP tag.  To using this class, you need to inject
+ * Spring Context via SetAppCtx() method. AclTag need Spring Context to get
+ * AclManger bean.
+ */
+public class AuthzImpl implements Authz {
+    //~ Static fields/initializers =============================================
+
+    static final int ALL_GRANTED = 1;
+    static final int ANY_GRANTED = 2;
+    static final int NONE_GRANTED = 3;
+
+    //~ Instance fields ========================================================
+
+    private ApplicationContext appCtx;
+
+    //~ Methods ================================================================
+
+    public boolean allGranted(String roles) {
+        return ifGranted(roles, ALL_GRANTED);
+    }
+
+    public boolean anyGranted(String roles) {
+        return ifGranted(roles, ANY_GRANTED);
+    }
+
+    public ApplicationContext getAppCtx() {
+        return appCtx;
+    }
+
+    /**
+     * implementation of AuthenticationTag
+     *
+     * @return DOCUMENT ME!
+     *
+     * @throws IllegalArgumentException DOCUMENT ME!
+     */
+    public String getPrincipal() {
+        MyAuthenticationTag authenticationTag = new MyAuthenticationTag();
+
+        authenticationTag.setOperation("username");
+
+        try {
+            authenticationTag.doStartTag();
+        } catch (JspException je) {
+            je.printStackTrace();
+            throw new IllegalArgumentException(je.getMessage());
+        }
+
+        return authenticationTag.getLastMessage();
+    }
+
+    /**
+     * implementation of AclTag
+     *
+     * @param domainObject DOCUMENT ME!
+     * @param permissions DOCUMENT ME!
+     *
+     * @return DOCUMENT ME!
+     *
+     * @throws IllegalArgumentException DOCUMENT ME!
+     */
+    public boolean hasPermission(Object domainObject, String permissions) {
+        MyAclTag aclTag = new MyAclTag();
+        aclTag.setPageContext(null);
+        aclTag.setContext(getAppCtx());
+        aclTag.setDomainObject(domainObject);
+        aclTag.setHasPermission(permissions);
+
+        int result = -1;
+
+        try {
+            result = aclTag.doStartTag();
+        } catch (JspException je) {
+            throw new IllegalArgumentException(je.getMessage());
+        }
+
+        if (Tag.EVAL_BODY_INCLUDE == result) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * implementation of AuthorizeTag
+     *
+     * @param roles DOCUMENT ME!
+     * @param grantType DOCUMENT ME!
+     *
+     * @return DOCUMENT ME!
+     *
+     * @throws IllegalArgumentException DOCUMENT ME!
+     */
+    private boolean ifGranted(String roles, int grantType) {
+        AuthorizeTag authorizeTag = new AuthorizeTag();
+
+        int result = -1;
+
+        try {
+            switch (grantType) {
+            case ALL_GRANTED:
+                authorizeTag.setIfAllGranted(roles);
+
+                break;
+
+            case ANY_GRANTED:
+                authorizeTag.setIfAnyGranted(roles);
+
+                break;
+
+            case NONE_GRANTED:
+                authorizeTag.setIfNotGranted(roles);
+
+                break;
+
+            default:
+                throw new IllegalArgumentException("invalid granted type : "
+                    + grantType + " role=" + roles);
+            }
+
+            result = authorizeTag.doStartTag();
+        } catch (JspException je) {
+            throw new IllegalArgumentException(je.getMessage());
+        }
+
+        if (Tag.EVAL_BODY_INCLUDE == result) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    public boolean noneGranted(String roles) {
+        return ifGranted(roles, NONE_GRANTED);
+    }
+
+    /**
+     * test case can use this class to mock application context with aclManager
+     * bean in it.
+     *
+     * @param appCtx DOCUMENT ME!
+     */
+    public void setAppCtx(ApplicationContext appCtx) {
+        this.appCtx = appCtx;
+    }
+
+    //~ Inner Classes ==========================================================
+
+    /**
+     * AclTag need to access the application context via the <code>
+     * WebApplicationContextUtils</code> and locate an {@link AclManager}.
+     * WebApplicationContextUtils get application context via ServletContext.
+     * I decided to let the Authz provide the Spring application context.
+     */
+    private class MyAclTag extends AclTag {
+        private static final long serialVersionUID = 6752340622125924108L;
+        ApplicationContext context;
+
+        protected ApplicationContext getContext(PageContext pageContext) {
+            return context;
+        }
+
+        protected void setContext(ApplicationContext context) {
+            this.context = context;
+        }
+    }
+
+    /**
+     * it must output somthing to JSP page, so have to override the
+     * writeMessage method to avoid JSP related operation. Get Idea from Acegi
+     * Test class.
+     */
+    private class MyAuthenticationTag extends AuthenticationTag {
+        private static final long serialVersionUID = -1094246833893599161L;
+        String lastMessage = null;
+
+        public String getLastMessage() {
+            return lastMessage;
+        }
+
+        protected void writeMessage(String msg) throws JspException {
+            lastMessage = msg;
+        }
+    }
+}

+ 98 - 0
core/src/test/java/org/acegisecurity/taglibs/velocity/AuthzImplAttributeTest.java

@@ -0,0 +1,98 @@
+/* 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 org.acegisecurity.taglibs.velocity;
+
+import junit.framework.TestCase;
+
+import org.acegisecurity.GrantedAuthority;
+import org.acegisecurity.GrantedAuthorityImpl;
+
+import org.acegisecurity.context.SecurityContextHolder;
+import org.acegisecurity.context.SecurityContextImpl;
+
+import org.acegisecurity.providers.TestingAuthenticationToken;
+
+import javax.servlet.jsp.JspException;
+
+
+/**
+ * DOCUMENT ME!
+ */
+public class AuthzImplAttributeTest extends TestCase {
+    //~ Instance fields ========================================================
+
+    private final Authz authz = new AuthzImpl();
+    private TestingAuthenticationToken currentUser;
+
+    //~ Methods ================================================================
+
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        currentUser = new TestingAuthenticationToken("abc", "123",
+                new GrantedAuthority[] {new GrantedAuthorityImpl(
+                        "ROLE_SUPERVISOR"), new GrantedAuthorityImpl(
+                        "ROLE_RESTRICTED"),});
+
+        SecurityContextHolder.getContext().setAuthentication(currentUser);
+    }
+
+    protected void tearDown() throws Exception {
+        SecurityContextHolder.setContext(new SecurityContextImpl());
+    }
+
+    public void testAssertsIfAllGrantedSecond() {
+        boolean r1 = authz.allGranted("ROLE_SUPERVISOR,ROLE_SUPERTELLER");
+        boolean r2 = authz.anyGranted("ROLE_RESTRICTED");
+
+        //prevents request - principal is missing ROLE_SUPERTELLE
+        assertFalse(r1 && r2);
+    }
+
+    public void testAssertsIfAnyGrantedLast() {
+        boolean r2 = authz.anyGranted("ROLE_BANKER");
+
+        // prevents request - principal is missing ROLE_BANKER
+        assertFalse(r2);
+    }
+
+    public void testAssertsIfNotGrantedFirst() {
+        boolean r1 = authz.allGranted("ROLE_SUPERVISOR,ROLE_RESTRICTED");
+        boolean r2 = authz.noneGranted("ROLE_RESTRICTED");
+        boolean r3 = authz.anyGranted("ROLE_SUPERVISOR");
+
+        //prevents request - principal has ROLE_RESTRICTED
+        assertFalse(r1 && r2 && r3);
+    }
+
+    public void testAssertsIfNotGrantedIgnoresWhitespaceInAttribute() {
+        //allows request - principal has ROLE_SUPERVISOR
+        assertTrue(authz.anyGranted(
+                "\tROLE_SUPERVISOR  \t, \r\n\t ROLE_TELLER "));
+    }
+
+    public void testIfAllGrantedIgnoresWhitespaceInAttribute() {
+        //allows request - principal has ROLE_RESTRICTED and ROLE_SUPERVISOR
+        assertTrue(authz.allGranted(
+                "\nROLE_SUPERVISOR\t,ROLE_RESTRICTED\t\n\r "));
+    }
+
+    public void testIfNotGrantedIgnoresWhitespaceInAttribute()
+        throws JspException {
+        //prevents request - principal does not have ROLE_TELLER
+        assertFalse(authz.allGranted(" \t  ROLE_TELLER \r"));
+    }
+}

+ 105 - 0
core/src/test/java/org/acegisecurity/taglibs/velocity/AuthzImplAuthorizeTagTest.java

@@ -0,0 +1,105 @@
+/* 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 org.acegisecurity.taglibs.velocity;
+
+import junit.framework.TestCase;
+
+import org.acegisecurity.GrantedAuthority;
+import org.acegisecurity.GrantedAuthorityImpl;
+
+import org.acegisecurity.context.SecurityContextHolder;
+import org.acegisecurity.context.SecurityContextImpl;
+
+import org.acegisecurity.providers.TestingAuthenticationToken;
+
+
+/**
+ * DOCUMENT ME!
+ */
+public class AuthzImplAuthorizeTagTest extends TestCase {
+    //~ Instance fields ========================================================
+
+    private Authz authz = new AuthzImpl();
+    private TestingAuthenticationToken currentUser;
+
+    //~ Methods ================================================================
+
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        currentUser = new TestingAuthenticationToken("abc", "123",
+                new GrantedAuthority[] {new GrantedAuthorityImpl(
+                        "ROLE_SUPERVISOR"), new GrantedAuthorityImpl(
+                        "ROLE_TELLER"),});
+
+        SecurityContextHolder.getContext().setAuthentication(currentUser);
+    }
+
+    protected void tearDown() throws Exception {
+        SecurityContextHolder.setContext(new SecurityContextImpl());
+    }
+
+    public void testAlwaysReturnsUnauthorizedIfNoUserFound() {
+        SecurityContextHolder.getContext().setAuthentication(null);
+
+        //prevents request - no principal in Context
+        assertFalse(authz.allGranted("ROLE_TELLER"));
+    }
+
+    public void testDefaultsToNotOutputtingBodyWhenNoRequiredAuthorities() {
+        //prevents body output - no authorities granted
+        assertFalse(authz.allGranted(""));
+        assertFalse(authz.anyGranted(""));
+        assertFalse(authz.noneGranted(""));
+    }
+
+    public void testOutputsBodyIfOneRolePresent() {
+        //authorized - ROLE_TELLER in both sets
+        assertTrue(authz.anyGranted("ROLE_TELLER"));
+    }
+
+    public void testOutputsBodyWhenAllGranted() {
+        // allows request - all required roles granted on principal
+        assertTrue(authz.allGranted("ROLE_SUPERVISOR,ROLE_TELLER"));
+    }
+
+    public void testOutputsBodyWhenNotGrantedSatisfied() {
+        // allows request - principal doesn't have ROLE_BANKER
+        assertTrue(authz.noneGranted("ROLE_BANKER"));
+    }
+
+    public void testPreventsBodyOutputIfNoSecureContext() {
+        SecurityContextHolder.getContext().setAuthentication(null);
+
+        // prevents output - no context defined
+        assertFalse(authz.anyGranted("ROLE_BANKER"));
+    }
+
+    public void testSkipsBodyIfNoAnyRolePresent() {
+        // unauthorized - ROLE_BANKER not in granted authorities
+        assertFalse(authz.anyGranted("ROLE_BANKER"));
+    }
+
+    public void testSkipsBodyWhenMissingAnAllGranted() {
+        //  prevents request - missing ROLE_BANKER on principal
+        assertFalse(authz.allGranted("ROLE_SUPERVISOR,ROLE_TELLER,ROLE_BANKER"));
+    }
+
+    public void testSkipsBodyWhenNotGrantedUnsatisfied() {
+        //  prevents request - principal has ROLE_TELLER
+        assertFalse(authz.noneGranted("ROLE_TELLER"));
+    }
+}

+ 247 - 0
core/src/test/java/org/acegisecurity/taglibs/velocity/AuthzImplTest.java

@@ -0,0 +1,247 @@
+/* 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 org.acegisecurity.taglibs.velocity;
+
+import junit.framework.TestCase;
+
+import org.acegisecurity.Authentication;
+import org.acegisecurity.GrantedAuthority;
+import org.acegisecurity.MockAclManager;
+
+import org.acegisecurity.acl.AclEntry;
+import org.acegisecurity.acl.AclManager;
+import org.acegisecurity.acl.basic.MockAclObjectIdentity;
+import org.acegisecurity.acl.basic.SimpleAclEntry;
+
+import org.acegisecurity.context.SecurityContextHolder;
+
+import org.acegisecurity.providers.TestingAuthenticationToken;
+
+import org.acegisecurity.userdetails.User;
+
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.support.StaticApplicationContext;
+
+
+/**
+ * DOCUMENT ME!
+ */
+public class AuthzImplTest extends TestCase {
+    //~ Instance fields ========================================================
+
+    private Authz authz = new AuthzImpl();
+    private ConfigurableApplicationContext ctx;
+
+    //~ Methods ================================================================
+
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        /*String[] paths = { "applicationEmpty.xml" };
+           ctx = new ClassPathXmlApplicationContext(paths);*/
+        ctx = new StaticApplicationContext();
+
+        // Create an AclManager
+        AclManager aclManager = new MockAclManager("object1", "marissa",
+                new AclEntry[] {new MockAclEntry(), new SimpleAclEntry(
+                        "marissa", new MockAclObjectIdentity(), null,
+                        SimpleAclEntry.ADMINISTRATION), new SimpleAclEntry(
+                        "marissa", new MockAclObjectIdentity(), null,
+                        SimpleAclEntry.READ)});
+
+        // Register the AclManager into our ApplicationContext
+        ctx.getBeanFactory().registerSingleton("aclManager", aclManager);
+    }
+
+    public void testIllegalArgumentExceptionThrownIfHasPermissionNotValidFormat() {
+        Authentication auth = new TestingAuthenticationToken("john", "crow",
+                new GrantedAuthority[] {});
+        SecurityContextHolder.getContext().setAuthentication(auth);
+
+        authz.setAppCtx(ctx);
+
+        String permissions = "0,5, 6"; // shouldn't be any space
+
+        try {
+            authz.hasPermission(null, permissions);
+        } catch (IllegalArgumentException iae) {
+            assertTrue(true);
+        }
+
+        SecurityContextHolder.getContext().setAuthentication(null);
+    }
+
+    public void testInclusionDeniedWhenAclManagerUnawareOfObject() {
+        Authentication auth = new TestingAuthenticationToken("marissa",
+                "koala", new GrantedAuthority[] {});
+        SecurityContextHolder.getContext().setAuthentication(auth);
+
+        authz.setAppCtx(ctx);
+
+        boolean result = authz.hasPermission(new Integer(54),
+                new Long(SimpleAclEntry.ADMINISTRATION).toString());
+
+        assertFalse(result);
+
+        SecurityContextHolder.getContext().setAuthentication(null);
+    }
+
+    public void testInclusionDeniedWhenNoListOfPermissionsGiven() {
+        Authentication auth = new TestingAuthenticationToken("marissa",
+                "koala", new GrantedAuthority[] {});
+        SecurityContextHolder.getContext().setAuthentication(auth);
+        authz.setAppCtx(ctx);
+
+        boolean result = authz.hasPermission("object1", null);
+
+        assertFalse(result);
+
+        SecurityContextHolder.getContext().setAuthentication(null);
+    }
+
+    public void testInclusionDeniedWhenPrincipalDoesNotHoldAnyPermissions() {
+        Authentication auth = new TestingAuthenticationToken("john", "crow",
+                new GrantedAuthority[] {});
+        SecurityContextHolder.getContext().setAuthentication(auth);
+
+        authz.setAppCtx(ctx);
+
+        String permissions = new Integer(SimpleAclEntry.ADMINISTRATION) + ","
+            + new Integer(SimpleAclEntry.READ);
+
+        boolean result = authz.hasPermission("object1", permissions);
+
+        assertFalse(result);
+
+        SecurityContextHolder.getContext().setAuthentication(null);
+    }
+
+    public void testInclusionDeniedWhenPrincipalDoesNotHoldRequiredPermissions() {
+        Authentication auth = new TestingAuthenticationToken("marissa",
+                "koala", new GrantedAuthority[] {});
+        SecurityContextHolder.getContext().setAuthentication(auth);
+        authz.setAppCtx(ctx);
+
+        String permissions = new Integer(SimpleAclEntry.DELETE).toString();
+
+        boolean result = authz.hasPermission("object1", permissions);
+
+        assertFalse(result);
+
+        SecurityContextHolder.getContext().setAuthentication(null);
+    }
+
+    public void testInclusionDeniedWhenSecurityContextEmpty() {
+        SecurityContextHolder.getContext().setAuthentication(null);
+
+        authz.setAppCtx(ctx);
+
+        String permissions = new Long(SimpleAclEntry.ADMINISTRATION).toString();
+
+        boolean result = authz.hasPermission("object1", permissions);
+
+        assertFalse(result);
+
+        SecurityContextHolder.getContext().setAuthentication(null);
+    }
+
+    public void testInclusionPermittedWhenDomainObjectIsNull() {
+        authz.setAppCtx(ctx);
+
+        String permissions = new Integer(SimpleAclEntry.READ).toString();
+
+        boolean result = authz.hasPermission(null, permissions);
+
+        assertTrue(result);
+    }
+
+    public void testOperationWhenPrincipalHoldsPermissionOfMultipleList() {
+        Authentication auth = new TestingAuthenticationToken("marissa",
+                "koala", new GrantedAuthority[] {});
+        SecurityContextHolder.getContext().setAuthentication(auth);
+
+        authz.setAppCtx(ctx);
+
+        String permissions = new Integer(SimpleAclEntry.ADMINISTRATION) + ","
+            + new Integer(SimpleAclEntry.READ);
+
+        boolean result = authz.hasPermission("object1", permissions);
+
+        assertTrue(result);
+
+        SecurityContextHolder.getContext().setAuthentication(null);
+    }
+
+    public void testOperationWhenPrincipalHoldsPermissionOfSingleList() {
+        Authentication auth = new TestingAuthenticationToken("marissa",
+                "koala", new GrantedAuthority[] {});
+        SecurityContextHolder.getContext().setAuthentication(auth);
+
+        authz.setAppCtx(ctx);
+
+        String permissions = new Integer(SimpleAclEntry.READ).toString();
+
+        boolean result = authz.hasPermission("object1", permissions);
+
+        assertTrue(result);
+        SecurityContextHolder.getContext().setAuthentication(null);
+    }
+
+    /*
+     * Test method for 'com.alibaba.exodus2.web.common.security.pulltool.AuthzImpl.getPrincipal()'
+     */
+    public void testOperationWhenPrincipalIsAString() {
+        Authentication auth = new TestingAuthenticationToken("marissaAsString",
+                "koala", new GrantedAuthority[] {});
+        SecurityContextHolder.getContext().setAuthentication(auth);
+
+        assertEquals("marissaAsString", authz.getPrincipal());
+    }
+
+    public void testOperationWhenPrincipalIsAUserDetailsInstance() {
+        Authentication auth = new TestingAuthenticationToken(new User(
+                    "marissaUserDetails", "koala", true, true, true, true,
+                    new GrantedAuthority[] {}), "koala",
+                new GrantedAuthority[] {});
+        SecurityContextHolder.getContext().setAuthentication(auth);
+
+        assertEquals("marissaUserDetails", authz.getPrincipal());
+    }
+
+    public void testOperationWhenPrincipalIsNull() {
+        Authentication auth = new TestingAuthenticationToken(null, "koala",
+                new GrantedAuthority[] {});
+        SecurityContextHolder.getContext().setAuthentication(auth);
+
+        assertNull(authz.getPrincipal());
+    }
+
+    public void testOperationWhenSecurityContextIsNull() {
+        SecurityContextHolder.getContext().setAuthentication(null);
+
+        assertEquals(null, authz.getPrincipal());
+
+        SecurityContextHolder.getContext().setAuthentication(null);
+    }
+
+    //~ Inner Classes ==========================================================
+
+    private class MockAclEntry implements AclEntry {
+        private static final long serialVersionUID = 1L;
+
+        // just so AclTag iterates some different types of AclEntrys
+    }
+}