You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2013/01/04 16:14:59 UTC

[2/6] git commit: ISIS-290: more on the shiro security integration.

ISIS-290: more on the shiro security integration.


Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/4ceaab88
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/4ceaab88
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/4ceaab88

Branch: refs/heads/master
Commit: 4ceaab8813277ed06da07a119fff7f4f276d5adb
Parents: 95c0b55
Author: Dan Haywood <da...@apache.org>
Authored: Thu Jan 3 14:38:33 2013 +0000
Committer: Dan Haywood <da...@apache.org>
Committed: Fri Jan 4 09:21:38 2013 +0000

----------------------------------------------------------------------
 component/security/shiro/pom.xml                   |   11 +
 .../shiro/ShiroAuthenticatorOrAuthorizor.java      |   84 +++++++-
 .../ShiroAuthenticationManagerInstaller.java       |    5 +-
 ...hiroSecurityManagerThreadLocalBinderFilter.java |   44 ++++
 .../shiro/ShiroAuthenticatorOrAuthorizorTest.java  |  167 +++++++++++++++
 .../security/shiro/ShiroAuthenticatorTester.java   |  149 -------------
 .../security/shiro/WildcardPermissionTest.java     |  124 +++++++++++
 .../shiro/authorization/ShiroAuthorizorTester.java |  150 -------------
 .../security/shiro/src/test/resources/shiro.ini    |   38 ++--
 .../authentication/standard/Authenticator.java     |   12 +-
 .../standard/AuthenticatorAbstract.java            |   14 ++
 core/runtime/pom.xml                               |    1 -
 .../quickstart_wicket_restful_jdo/pom.xml          |    8 +
 .../viewer-webapp/pom.xml                          |   43 +---
 .../src/main/webapp/WEB-INF/isis.properties        |    3 +-
 .../src/main/webapp/WEB-INF/shiro.ini              |   49 +++++
 .../viewer-webapp/src/main/webapp/WEB-INF/web.xml  |   28 +++-
 17 files changed, 553 insertions(+), 377 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/4ceaab88/component/security/shiro/pom.xml
----------------------------------------------------------------------
diff --git a/component/security/shiro/pom.xml b/component/security/shiro/pom.xml
index ca2d9e8..a949814 100644
--- a/component/security/shiro/pom.xml
+++ b/component/security/shiro/pom.xml
@@ -128,6 +128,17 @@
             <version>${shiro.version}</version>
         </dependency>
 
+	    <dependency>
+            <groupId>org.apache.geronimo.specs</groupId>
+            <artifactId>geronimo-servlet_2.5_spec</artifactId>
+		    <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.shiro</groupId>
+            <artifactId>shiro-web</artifactId>
+            <version>${shiro.version}</version>
+        </dependency>
 
 	</dependencies>
 </project>

http://git-wip-us.apache.org/repos/asf/isis/blob/4ceaab88/component/security/shiro/src/main/java/org/apache/isis/security/shiro/ShiroAuthenticatorOrAuthorizor.java
----------------------------------------------------------------------
diff --git a/component/security/shiro/src/main/java/org/apache/isis/security/shiro/ShiroAuthenticatorOrAuthorizor.java b/component/security/shiro/src/main/java/org/apache/isis/security/shiro/ShiroAuthenticatorOrAuthorizor.java
index c31e663..3507870 100644
--- a/component/security/shiro/src/main/java/org/apache/isis/security/shiro/ShiroAuthenticatorOrAuthorizor.java
+++ b/component/security/shiro/src/main/java/org/apache/isis/security/shiro/ShiroAuthenticatorOrAuthorizor.java
@@ -24,6 +24,8 @@ import java.util.Collections;
 import java.util.List;
 
 import org.apache.isis.applib.Identifier;
+import org.apache.isis.applib.Identifier.Depth;
+import org.apache.isis.applib.Identifier.Type;
 import org.apache.isis.core.commons.authentication.AuthenticationSession;
 import org.apache.isis.core.commons.config.IsisConfiguration;
 import org.apache.isis.core.runtime.authentication.AuthenticationManagerInstaller;
@@ -50,9 +52,11 @@ import org.apache.shiro.mgt.DefaultSecurityManager;
 import org.apache.shiro.mgt.RealmSecurityManager;
 import org.apache.shiro.mgt.SecurityManager;
 import org.apache.shiro.realm.Realm;
+import org.apache.shiro.subject.PrincipalCollection;
 import org.apache.shiro.subject.Subject;
 import org.apache.shiro.util.Factory;
 
+import com.google.common.base.Splitter;
 import com.google.common.collect.Lists;
 
 /**
@@ -61,7 +65,8 @@ import com.google.common.collect.Lists;
  * instantiated twice, once in the role of {@link Authenticator} and once in the role of the {@link Authorizor}.
  * 
  * <p>
- * However, although there are two objects, they are set up to share the same {@link SecurityManager Shiro SecurityManager}.
+ * However, although there are two objects, they are set up to share the same {@link SecurityManager Shiro SecurityManager}
+ * (bound to a thread-local).
  */
 public class ShiroAuthenticatorOrAuthorizor implements Authenticator, Authorizor {
 
@@ -103,13 +108,33 @@ public class ShiroAuthenticatorOrAuthorizor implements Authenticator, Authorizor
         try {
             return (DefaultSecurityManager) SecurityUtils.getSecurityManager();
         } catch(UnavailableSecurityManagerException ex) {
-            Factory<SecurityManager> factory = new IniSecurityManagerFactory(configuration.getString("isis.security.shiro.iniLocation", "classpath:shiro.ini"));
+            String shiroIniLocation = lookupIniLocationFrom(configuration);
+
+            Factory<SecurityManager> factory = new IniSecurityManagerFactory(shiroIniLocation);
             SecurityManager securityManager = factory.getInstance();
             SecurityUtils.setSecurityManager(securityManager);
             return securityManager;
         }
     }
 
+    private static String lookupIniLocationFrom(final IsisConfiguration configuration) {
+        String configuredValue;
+        
+        configuredValue = configuration.getString("isis.security.shiro.iniLocation");
+        if(configuredValue != null) {
+            return configuredValue;
+        }
+        configuredValue = configuration.getString("isis.authentication.shiro.iniLocation");
+        if(configuredValue != null) {
+            return configuredValue;
+        }
+        configuredValue = configuration.getString("isis.authorization.shiro.iniLocation");
+        if(configuredValue != null) {
+            return configuredValue;
+        }
+        return "classpath:shiro.ini";
+    }
+
     @Override
     public void shutdown() {
         //
@@ -193,35 +218,72 @@ public class ShiroAuthenticatorOrAuthorizor implements Authenticator, Authorizor
     }
 
 
+    /**
+     * UNUSED (see [ISIS-292]).
+     */
+    @Override
+    public boolean isValid(AuthenticationRequest request) {
+        return false;
+    }
+
     // //////////////////////////////////////////////////////
     // Authorizor API
     // //////////////////////////////////////////////////////
 
     @Override
     public boolean isVisibleInAnyRole(Identifier identifier) {
-        return false;
+        return isPermitted(identifier, "r");
     }
 
     @Override
     public boolean isUsableInAnyRole(Identifier identifier) {
-        return false;
+        return isPermitted(identifier, "w");
+    }
+
+    private boolean isPermitted(Identifier identifier, String qualifier) {
+        if(realmSecurityManager == null) {
+            // cannot do permission checking if the security manager is not a RealmSecurityManager
+            return false;
+        }
+
+        String permission = asPermissionsString(identifier) + ":" + qualifier;
+
+        PrincipalCollection principals = SecurityUtils.getSubject().getPrincipals();
+        return realmSecurityManager.isPermitted(principals, permission);
     }
 
+    private String asPermissionsString(Identifier identifier) {
+        String packageName;
+        String className;
+        String fullyQualifiedClassName = identifier.getClassName();
+        int lastDot = fullyQualifiedClassName.lastIndexOf('.');
+        if(lastDot > 0) {
+            packageName =fullyQualifiedClassName.substring(0, lastDot);
+            className = fullyQualifiedClassName.substring(lastDot+1);
+        } else {
+            packageName = "";
+            className = fullyQualifiedClassName;
+        }
+        return packageName + ":" + className + ":" + identifier.getMemberName();
+    }
+
+    /**
+     * Returns <tt>false</tt> because the checking across all roles is done in
+     * {@link #isVisibleInAnyRole(Identifier)}, which is always called prior to this.
+     */
     @Override
     public boolean isVisibleInRole(String role, Identifier identifier) {
-        if(shiroSecurityManager instanceof RealmSecurityManager) {
-            
-        }
-        // TODO Auto-generated method stub
         return false;
     }
 
+    /**
+     * Returns <tt>false</tt> because the checking across all roles is done in
+     * {@link #isUsableInAnyRole(Identifier)}, which is always called prior to this.
+     */
     @Override
     public boolean isUsableInRole(String role, Identifier identifier) {
-        // TODO Auto-generated method stub
         return false;
     }
-
     
     // //////////////////////////////////////////////////////
     // Injected (via constructor)
@@ -231,4 +293,6 @@ public class ShiroAuthenticatorOrAuthorizor implements Authenticator, Authorizor
         return configuration;
     }
 
+
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/4ceaab88/component/security/shiro/src/main/java/org/apache/isis/security/shiro/authentication/ShiroAuthenticationManagerInstaller.java
----------------------------------------------------------------------
diff --git a/component/security/shiro/src/main/java/org/apache/isis/security/shiro/authentication/ShiroAuthenticationManagerInstaller.java b/component/security/shiro/src/main/java/org/apache/isis/security/shiro/authentication/ShiroAuthenticationManagerInstaller.java
index b462614..7702e40 100644
--- a/component/security/shiro/src/main/java/org/apache/isis/security/shiro/authentication/ShiroAuthenticationManagerInstaller.java
+++ b/component/security/shiro/src/main/java/org/apache/isis/security/shiro/authentication/ShiroAuthenticationManagerInstaller.java
@@ -21,14 +21,13 @@ package org.apache.isis.security.shiro.authentication;
 
 import java.util.List;
 
-import com.google.common.collect.Lists;
-
 import org.apache.isis.core.commons.config.IsisConfiguration;
 import org.apache.isis.core.runtime.authentication.AuthenticationManagerStandardInstallerAbstractForDfltRuntime;
 import org.apache.isis.core.runtime.authentication.standard.Authenticator;
-import org.apache.isis.core.runtime.system.context.IsisContext;
 import org.apache.isis.security.shiro.ShiroAuthenticatorOrAuthorizor;
 
+import com.google.common.collect.Lists;
+
 public class ShiroAuthenticationManagerInstaller extends AuthenticationManagerStandardInstallerAbstractForDfltRuntime {
 
     public static String NAME = "shiro";

http://git-wip-us.apache.org/repos/asf/isis/blob/4ceaab88/component/security/shiro/src/main/java/org/apache/isis/security/shiro/web/IsisShiroSecurityManagerThreadLocalBinderFilter.java
----------------------------------------------------------------------
diff --git a/component/security/shiro/src/main/java/org/apache/isis/security/shiro/web/IsisShiroSecurityManagerThreadLocalBinderFilter.java b/component/security/shiro/src/main/java/org/apache/isis/security/shiro/web/IsisShiroSecurityManagerThreadLocalBinderFilter.java
new file mode 100644
index 0000000..d08b70f
--- /dev/null
+++ b/component/security/shiro/src/main/java/org/apache/isis/security/shiro/web/IsisShiroSecurityManagerThreadLocalBinderFilter.java
@@ -0,0 +1,44 @@
+package org.apache.isis.security.shiro.web;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+import org.apache.shiro.mgt.SecurityManager;
+import org.apache.shiro.util.ThreadContext;
+import org.apache.shiro.web.env.WebEnvironment;
+import org.apache.shiro.web.util.WebUtils;
+
+public class IsisShiroSecurityManagerThreadLocalBinderFilter implements Filter {
+
+    private FilterConfig filterConfig;
+
+    @Override
+    public void init(FilterConfig filterConfig) throws ServletException {
+        this.filterConfig = filterConfig;
+    }
+
+    @Override
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
+        ServletContext servletContext = filterConfig.getServletContext();
+        WebEnvironment webEnvironment = WebUtils.getWebEnvironment(servletContext);
+        SecurityManager securityManager = webEnvironment.getSecurityManager();
+        ThreadContext.bind(securityManager);
+        try {
+            doFilter(request, response, chain);
+        } finally {
+            ThreadContext.unbindSecurityManager();
+        }
+    }
+
+    @Override
+    public void destroy() {
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/4ceaab88/component/security/shiro/src/test/java/org/apache/isis/security/shiro/ShiroAuthenticatorOrAuthorizorTest.java
----------------------------------------------------------------------
diff --git a/component/security/shiro/src/test/java/org/apache/isis/security/shiro/ShiroAuthenticatorOrAuthorizorTest.java b/component/security/shiro/src/test/java/org/apache/isis/security/shiro/ShiroAuthenticatorOrAuthorizorTest.java
new file mode 100644
index 0000000..b6c0d94
--- /dev/null
+++ b/component/security/shiro/src/test/java/org/apache/isis/security/shiro/ShiroAuthenticatorOrAuthorizorTest.java
@@ -0,0 +1,167 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.isis.security.shiro;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.assertThat;
+
+import org.apache.isis.applib.Identifier;
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.commons.config.IsisConfiguration;
+import org.apache.isis.core.runtime.authentication.AuthenticationRequest;
+import org.apache.isis.core.runtime.authentication.AuthenticationRequestPassword;
+import org.apache.isis.core.unittestsupport.jmock.auto.Mock;
+import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2;
+import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2.Mode;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.authc.AuthenticationException;
+import org.apache.shiro.authc.IncorrectCredentialsException;
+import org.apache.shiro.authc.LockedAccountException;
+import org.apache.shiro.authc.UnknownAccountException;
+import org.apache.shiro.authc.UsernamePasswordToken;
+import org.apache.shiro.config.IniSecurityManagerFactory;
+import org.apache.shiro.mgt.SecurityManager;
+import org.apache.shiro.session.Session;
+import org.apache.shiro.subject.Subject;
+import org.apache.shiro.util.Factory;
+import org.jmock.Expectations;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class ShiroAuthenticatorOrAuthorizorTest {
+
+    @Rule
+    public JUnitRuleMockery2 context = JUnitRuleMockery2.createFor(Mode.INTERFACES_AND_CLASSES);
+
+    @Mock
+    private IsisConfiguration mockConfiguration;
+    
+    private ShiroAuthenticatorOrAuthorizor authOrAuth;
+
+    @Before
+    public void setUp() throws Exception {
+        authOrAuth = new ShiroAuthenticatorOrAuthorizor(mockConfiguration);
+    }
+    
+    @Test
+    public void happyCase() throws Exception {
+
+        context.checking(new Expectations() {
+            {
+                allowing(mockConfiguration).getString(with("isis.security.shiro.iniLocation"));
+                will(returnValue("classpath:shiro.ini"));
+            }
+        });
+
+
+        authOrAuth.init();
+        assertThat(authOrAuth.canAuthenticate(AuthenticationRequestPassword.class), is(true));
+        
+        AuthenticationRequest ar = new AuthenticationRequestPassword("lonestarr", "vespa");
+        AuthenticationSession isisAuthSession = authOrAuth.authenticate(ar, null);
+        
+        assertThat(isisAuthSession, is(not(nullValue())));
+        assertThat(isisAuthSession.getUserName(), is("lonestarr"));
+        assertThat(isisAuthSession.getValidationCode(), is(nullValue()));
+
+        Identifier changeAddressIdentifier = Identifier.actionIdentifier("com.mycompany.myapp.Customer", "changeAddress", String.class, String.class);
+        assertThat(authOrAuth.isVisibleInAnyRole(changeAddressIdentifier), is(true));
+        
+        Identifier changeEmailIdentifier = Identifier.actionIdentifier("com.mycompany.myapp.Customer", "changeEmail", String.class);
+        assertThat(authOrAuth.isVisibleInAnyRole(changeEmailIdentifier), is(true));
+
+        Identifier submitOrderIdentifier = Identifier.actionIdentifier("com.mycompany.myapp.Order", "submit");
+        assertThat(authOrAuth.isVisibleInAnyRole(submitOrderIdentifier), is(true));
+
+        Identifier cancelOrderIdentifier = Identifier.actionIdentifier("com.mycompany.myapp.Order", "cancel");
+        assertThat(authOrAuth.isVisibleInAnyRole(cancelOrderIdentifier), is(false));
+
+        
+//        // Use the shiro.ini file at the root of the classpath
+//        // (file: and url: prefixes load from files and urls respectively):
+//        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
+//        SecurityManager securityManager = factory.getInstance();
+//
+//        // for this simple example quickstart, make the SecurityManager
+//        // accessible as a JVM singleton.  Most applications wouldn't do this
+//        // and instead rely on their container configuration or web.xml for
+//        // webapps.  That is outside the scope of this simple quickstart, so
+//        // we'll just do the bare minimum so you can continue to get a feel
+//        // for things.
+//        SecurityUtils.setSecurityManager(securityManager);
+//
+//        // Now that a simple Shiro environment is set up, let's see what you can do:
+//
+//        // get the currently executing user:
+//        Subject currentUser = SecurityUtils.getSubject();
+//
+//        // Do some stuff with a Session (no need for a web or EJB container!!!)
+//        Session session = currentUser.getSession();
+//        session.setAttribute("someKey", "aValue");
+//        String value = (String) session.getAttribute("someKey");
+//        if (value.equals("aValue")) {
+//            System.out.println("Retrieved the correct value! [" + value + "]");
+//        }
+//
+//        // let's login the current user so we can check against roles and permissions:
+//        if (!currentUser.isAuthenticated()) {
+//            UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
+//            token.setRememberMe(true);
+//            try {
+//                currentUser.login(token);
+//            } catch (UnknownAccountException uae) {
+//                System.out.println("There is no user with username of " + token.getPrincipal());
+//            } catch (IncorrectCredentialsException ice) {
+//                System.out.println("Password for account " + token.getPrincipal() + " was incorrect!");
+//            } catch (LockedAccountException lae) {
+//                System.out.println("The account for username " + token.getPrincipal() + " is locked.  " +
+//                        "Please contact your administrator to unlock it.");
+//            }
+//            // ... catch more exceptions here (maybe custom ones specific to your application?
+//            catch (AuthenticationException ae) {
+//                //unexpected condition?  error?
+//            }
+//        }
+//
+//        //say who they are:
+//        //print their identifying principal (in this case, a username):
+//        System.out.println("User [" + currentUser.getPrincipal() + "] logged in successfully.");
+//
+//        //test a role:
+//        if (currentUser.hasRole("schwartz")) {
+//            System.out.println("May the Schwartz be with you!");
+//        } else {
+//            System.out.println("Hello, mere mortal.");
+//        }
+//
+//        //test a typed permission (not instance-level)
+//        if (currentUser.isPermitted("com.mycompany.myapp:Customer:changeAddress:w")) {
+//            System.out.println("You may invoke the customer's changeAddress action.");
+//        } else {
+//            System.out.println("Sorry, changing address is only allowed for schwartz masters only.");
+//        }
+//
+//        //all done - log out!
+//        currentUser.logout();
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/4ceaab88/component/security/shiro/src/test/java/org/apache/isis/security/shiro/ShiroAuthenticatorTester.java
----------------------------------------------------------------------
diff --git a/component/security/shiro/src/test/java/org/apache/isis/security/shiro/ShiroAuthenticatorTester.java b/component/security/shiro/src/test/java/org/apache/isis/security/shiro/ShiroAuthenticatorTester.java
deleted file mode 100644
index f7fade1..0000000
--- a/component/security/shiro/src/test/java/org/apache/isis/security/shiro/ShiroAuthenticatorTester.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you 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.apache.isis.security.shiro;
-
-import org.apache.isis.core.commons.config.IsisConfiguration;
-import org.apache.isis.core.runtime.authentication.AuthenticationRequestPassword;
-import org.apache.isis.core.runtime.system.context.IsisContext;
-import org.apache.isis.core.unittestsupport.jmock.auto.Mock;
-import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2;
-import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2.Mode;
-import org.apache.isis.security.shiro.ShiroAuthenticatorOrAuthorizor;
-import org.apache.shiro.SecurityUtils;
-import org.apache.shiro.authc.AuthenticationException;
-import org.apache.shiro.authc.IncorrectCredentialsException;
-import org.apache.shiro.authc.LockedAccountException;
-import org.apache.shiro.authc.UnknownAccountException;
-import org.apache.shiro.authc.UsernamePasswordToken;
-import org.apache.shiro.config.IniSecurityManagerFactory;
-import org.apache.shiro.mgt.SecurityManager;
-import org.apache.shiro.session.Session;
-import org.apache.shiro.subject.Subject;
-import org.apache.shiro.util.Factory;
-import org.jmock.Expectations;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-
-public class ShiroAuthenticatorTester {
-
-    @Rule
-    public JUnitRuleMockery2 context = JUnitRuleMockery2.createFor(Mode.INTERFACES_AND_CLASSES);
-
-    @Mock
-    private IsisConfiguration mockConfiguration;
-    
-    private ShiroAuthenticatorOrAuthorizor authenticator;
-
-    @Before
-    public void setUp() throws Exception {
-        authenticator = new ShiroAuthenticatorOrAuthorizor(mockConfiguration);
-    }
-    
-    @Test
-    public void xxx() throws Exception {
-
-        context.checking(new Expectations() {
-            {
-                allowing(mockConfiguration).getString("isis.authentication.shiro.iniClasspath");
-                will(returnValue("classpath:shiro.ini"));
-            }
-        });
-
-        
-        // Use the shiro.ini file at the root of the classpath
-        // (file: and url: prefixes load from files and urls respectively):
-        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
-        SecurityManager securityManager = factory.getInstance();
-
-        // for this simple example quickstart, make the SecurityManager
-        // accessible as a JVM singleton.  Most applications wouldn't do this
-        // and instead rely on their container configuration or web.xml for
-        // webapps.  That is outside the scope of this simple quickstart, so
-        // we'll just do the bare minimum so you can continue to get a feel
-        // for things.
-        SecurityUtils.setSecurityManager(securityManager);
-
-        // Now that a simple Shiro environment is set up, let's see what you can do:
-
-        // get the currently executing user:
-        Subject currentUser = SecurityUtils.getSubject();
-
-        // Do some stuff with a Session (no need for a web or EJB container!!!)
-        Session session = currentUser.getSession();
-        session.setAttribute("someKey", "aValue");
-        String value = (String) session.getAttribute("someKey");
-        if (value.equals("aValue")) {
-            System.out.println("Retrieved the correct value! [" + value + "]");
-        }
-
-        // let's login the current user so we can check against roles and permissions:
-        if (!currentUser.isAuthenticated()) {
-            UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
-            token.setRememberMe(true);
-            try {
-                currentUser.login(token);
-            } catch (UnknownAccountException uae) {
-                System.out.println("There is no user with username of " + token.getPrincipal());
-            } catch (IncorrectCredentialsException ice) {
-                System.out.println("Password for account " + token.getPrincipal() + " was incorrect!");
-            } catch (LockedAccountException lae) {
-                System.out.println("The account for username " + token.getPrincipal() + " is locked.  " +
-                        "Please contact your administrator to unlock it.");
-            }
-            // ... catch more exceptions here (maybe custom ones specific to your application?
-            catch (AuthenticationException ae) {
-                //unexpected condition?  error?
-            }
-        }
-
-        //say who they are:
-        //print their identifying principal (in this case, a username):
-        System.out.println("User [" + currentUser.getPrincipal() + "] logged in successfully.");
-
-        //test a role:
-        if (currentUser.hasRole("schwartz")) {
-            System.out.println("May the Schwartz be with you!");
-        } else {
-            System.out.println("Hello, mere mortal.");
-        }
-
-        //test a typed permission (not instance-level)
-        if (currentUser.isPermitted("lightsaber:weild")) {
-            System.out.println("You may use a lightsaber ring.  Use it wisely.");
-        } else {
-            System.out.println("Sorry, lightsaber rings are for schwartz masters only.");
-        }
-
-        //a (very powerful) Instance Level permission:
-        if (currentUser.isPermitted("winnebago:drive:eagle5")) {
-            System.out.println("You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'.  " +
-                    "Here are the keys - have fun!");
-        } else {
-            System.out.println("Sorry, you aren't allowed to drive the 'eagle5' winnebago!");
-        }
-
-        //all done - log out!
-        currentUser.logout();
-
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/4ceaab88/component/security/shiro/src/test/java/org/apache/isis/security/shiro/WildcardPermissionTest.java
----------------------------------------------------------------------
diff --git a/component/security/shiro/src/test/java/org/apache/isis/security/shiro/WildcardPermissionTest.java b/component/security/shiro/src/test/java/org/apache/isis/security/shiro/WildcardPermissionTest.java
new file mode 100644
index 0000000..438ebeb
--- /dev/null
+++ b/component/security/shiro/src/test/java/org/apache/isis/security/shiro/WildcardPermissionTest.java
@@ -0,0 +1,124 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.isis.security.shiro;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.assertThat;
+
+import org.apache.isis.core.commons.config.IsisConfiguration;
+import org.apache.isis.core.unittestsupport.jmock.auto.Mock;
+import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2;
+import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2.Mode;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.authc.AuthenticationException;
+import org.apache.shiro.authc.IncorrectCredentialsException;
+import org.apache.shiro.authc.LockedAccountException;
+import org.apache.shiro.authc.UnknownAccountException;
+import org.apache.shiro.authc.UsernamePasswordToken;
+import org.apache.shiro.authz.Permission;
+import org.apache.shiro.authz.permission.WildcardPermission;
+import org.apache.shiro.config.IniSecurityManagerFactory;
+import org.apache.shiro.mgt.SecurityManager;
+import org.apache.shiro.session.Session;
+import org.apache.shiro.subject.Subject;
+import org.apache.shiro.util.Factory;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+import org.jmock.Expectations;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class WildcardPermissionTest {
+
+
+    @Test
+    public void typicalUsageWithinIsis() throws Exception {
+        
+        // these are the permissions that Isis will check
+        WildcardPermission viewCustomerChangeAddress = new WildcardPermission("com.mycompany.myapp:Customer:changeAddress:r");
+        WildcardPermission useCustomerChangeAddress = new WildcardPermission("com.mycompany.myapp:Customer:changeAddress:w");
+
+        // and these are examples of permissions that will be associated with a user
+        assertThat(viewCustomerChangeAddress, permittedBy("com.mycompany.myapp:Customer:changeAddress:r"));
+        assertThat(viewCustomerChangeAddress, permittedBy("com.mycompany.myapp:Customer:changeAddress:*"));
+        assertThat(viewCustomerChangeAddress, permittedBy("com.mycompany.myapp:Customer:*:r"));
+        assertThat(viewCustomerChangeAddress, permittedBy("com.mycompany.myapp:*:*:r"));
+        assertThat(viewCustomerChangeAddress, permittedBy("*:*:*:r"));
+        assertThat(viewCustomerChangeAddress, permittedBy("*:*:*:*"));
+        assertThat(viewCustomerChangeAddress, permittedBy("*:*:*"));
+        assertThat(viewCustomerChangeAddress, permittedBy("*:*"));
+        assertThat(viewCustomerChangeAddress, permittedBy("*"));
+        assertThat(viewCustomerChangeAddress, permittedBy("*:Customer:*:r"));
+
+        assertThat(useCustomerChangeAddress, permittedBy("com.mycompany.myapp:Customer:changeAddress:w"));
+        assertThat(useCustomerChangeAddress, permittedBy("com.mycompany.myapp:Customer:changeAddress:*"));
+
+        // and these are some counterexamples
+        assertThat(viewCustomerChangeAddress, not(permittedBy("com.mycompany.myapp:Customer:changeAddress:w")));
+        assertThat(useCustomerChangeAddress, not(permittedBy("com.mycompany.myapp:Customer:changeAddress:r")));
+
+        assertThat(viewCustomerChangeAddress, not(permittedBy("com.mycompany.myapp:Customer:changePhoneNumber:r")));
+        assertThat(viewCustomerChangeAddress, not(permittedBy("com.mycompany.myapp:Order:changeAddress:r")));
+        assertThat(viewCustomerChangeAddress, not(permittedBy("xxx.mycompany.myapp:Customer:changeAddress:r")));
+        assertThat(viewCustomerChangeAddress, not(permittedBy("*:*:xxx")));
+        assertThat(viewCustomerChangeAddress, not(permittedBy("*:xxx")));
+        assertThat(viewCustomerChangeAddress, not(permittedBy("xxx")));
+    }
+
+    
+    @Test
+    public void defaultPackage() throws Exception {
+        
+        // these are the permissions that Isis will check
+        WildcardPermission viewCustomerChangeAddress = new WildcardPermission(":Customer:changeAddress:r");
+
+        // and these are examples of permissions that will be associated with a user
+        assertThat(viewCustomerChangeAddress, permittedBy(":Customer:changeAddress:r"));
+        assertThat(viewCustomerChangeAddress, permittedBy("*:Customer:changeAddress:r"));
+        assertThat(viewCustomerChangeAddress, permittedBy("*:Customer:changeAddress:*"));
+        assertThat(viewCustomerChangeAddress, permittedBy("*:Customer:changeAddress"));
+        assertThat(viewCustomerChangeAddress, permittedBy("*:Customer:*"));
+        assertThat(viewCustomerChangeAddress, permittedBy("*:Customer"));
+        assertThat(viewCustomerChangeAddress, permittedBy("*:*"));
+        assertThat(viewCustomerChangeAddress, permittedBy("*"));
+    }
+    
+    private static Matcher<? super Permission> permittedBy(final String permissionString) {
+        return implies(new WildcardPermission(permissionString));
+    }
+
+    private static Matcher<? super Permission> implies(final WildcardPermission wp) {
+        return new TypeSafeMatcher<Permission>() {
+
+            @Override
+            public void describeTo(Description description) {
+                description.appendText("implies " + wp.toString());
+            }
+
+            @Override
+            protected boolean matchesSafely(Permission item) {
+                return wp.implies(item);
+            }
+        };
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/4ceaab88/component/security/shiro/src/test/java/org/apache/isis/security/shiro/authorization/ShiroAuthorizorTester.java
----------------------------------------------------------------------
diff --git a/component/security/shiro/src/test/java/org/apache/isis/security/shiro/authorization/ShiroAuthorizorTester.java b/component/security/shiro/src/test/java/org/apache/isis/security/shiro/authorization/ShiroAuthorizorTester.java
deleted file mode 100644
index b1fc4dc..0000000
--- a/component/security/shiro/src/test/java/org/apache/isis/security/shiro/authorization/ShiroAuthorizorTester.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you 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.apache.isis.security.shiro.authorization;
-
-import org.apache.isis.core.commons.config.IsisConfiguration;
-import org.apache.isis.core.runtime.authentication.AuthenticationRequestPassword;
-import org.apache.isis.core.runtime.system.context.IsisContext;
-import org.apache.isis.core.unittestsupport.jmock.auto.Mock;
-import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2;
-import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2.Mode;
-import org.apache.isis.security.shiro.ShiroAuthenticatorOrAuthorizor;
-import org.apache.shiro.SecurityUtils;
-import org.apache.shiro.authc.AuthenticationException;
-import org.apache.shiro.authc.IncorrectCredentialsException;
-import org.apache.shiro.authc.LockedAccountException;
-import org.apache.shiro.authc.UnknownAccountException;
-import org.apache.shiro.authc.UsernamePasswordToken;
-import org.apache.shiro.config.IniSecurityManagerFactory;
-import org.apache.shiro.mgt.SecurityManager;
-import org.apache.shiro.session.Session;
-import org.apache.shiro.subject.Subject;
-import org.apache.shiro.util.Factory;
-import org.jmock.Expectations;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-
-public class ShiroAuthorizorTester {
-
-    @Rule
-    public JUnitRuleMockery2 context = JUnitRuleMockery2.createFor(Mode.INTERFACES_AND_CLASSES);
-
-    @Mock
-    private IsisConfiguration mockConfiguration;
-    
-    private ShiroAuthenticatorOrAuthorizor authenticator;
-
-    @Before
-    public void setUp() throws Exception {
-        authenticator = new ShiroAuthenticatorOrAuthorizor(mockConfiguration);
-    }
-    
-    @Test
-    public void xxx() throws Exception {
-
-        context.checking(new Expectations() {
-            {
-                allowing(mockConfiguration).getString("isis.authentication.shiro.iniClasspath");
-                will(returnValue("classpath:shiro.ini"));
-            }
-        });
-
-        
-        // Use the shiro.ini file at the root of the classpath
-        // (file: and url: prefixes load from files and urls respectively):
-        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
-        SecurityManager securityManager = factory.getInstance();
-
-        // for this simple example quickstart, make the SecurityManager
-        // accessible as a JVM singleton.  Most applications wouldn't do this
-        // and instead rely on their container configuration or web.xml for
-        // webapps.  That is outside the scope of this simple quickstart, so
-        // we'll just do the bare minimum so you can continue to get a feel
-        // for things.
-        SecurityUtils.setSecurityManager(securityManager);
-        
-
-        // Now that a simple Shiro environment is set up, let's see what you can do:
-
-        // get the currently executing user:
-        Subject currentUser = SecurityUtils.getSubject();
-
-        // Do some stuff with a Session (no need for a web or EJB container!!!)
-        Session session = currentUser.getSession();
-        session.setAttribute("someKey", "aValue");
-        String value = (String) session.getAttribute("someKey");
-        if (value.equals("aValue")) {
-            System.out.println("Retrieved the correct value! [" + value + "]");
-        }
-
-        // let's login the current user so we can check against roles and permissions:
-        if (!currentUser.isAuthenticated()) {
-            UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
-            token.setRememberMe(true);
-            try {
-                currentUser.login(token);
-            } catch (UnknownAccountException uae) {
-                System.out.println("There is no user with username of " + token.getPrincipal());
-            } catch (IncorrectCredentialsException ice) {
-                System.out.println("Password for account " + token.getPrincipal() + " was incorrect!");
-            } catch (LockedAccountException lae) {
-                System.out.println("The account for username " + token.getPrincipal() + " is locked.  " +
-                        "Please contact your administrator to unlock it.");
-            }
-            // ... catch more exceptions here (maybe custom ones specific to your application?
-            catch (AuthenticationException ae) {
-                //unexpected condition?  error?
-            }
-        }
-
-        //say who they are:
-        //print their identifying principal (in this case, a username):
-        System.out.println("User [" + currentUser.getPrincipal() + "] logged in successfully.");
-
-        //test a role:
-        if (currentUser.hasRole("schwartz")) {
-            System.out.println("May the Schwartz be with you!");
-        } else {
-            System.out.println("Hello, mere mortal.");
-        }
-
-        //test a typed permission (not instance-level)
-        if (currentUser.isPermitted("lightsaber:weild")) {
-            System.out.println("You may use a lightsaber ring.  Use it wisely.");
-        } else {
-            System.out.println("Sorry, lightsaber rings are for schwartz masters only.");
-        }
-
-        //a (very powerful) Instance Level permission:
-        if (currentUser.isPermitted("winnebago:drive:eagle5")) {
-            System.out.println("You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'.  " +
-                    "Here are the keys - have fun!");
-        } else {
-            System.out.println("Sorry, you aren't allowed to drive the 'eagle5' winnebago!");
-        }
-
-        //all done - log out!
-        currentUser.logout();
-
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/4ceaab88/component/security/shiro/src/test/resources/shiro.ini
----------------------------------------------------------------------
diff --git a/component/security/shiro/src/test/resources/shiro.ini b/component/security/shiro/src/test/resources/shiro.ini
index adca38c..e865229 100644
--- a/component/security/shiro/src/test/resources/shiro.ini
+++ b/component/security/shiro/src/test/resources/shiro.ini
@@ -16,12 +16,7 @@
 # specific language governing permissions and limitations
 # under the License.
 #
-# =============================================================================
-# Quickstart INI Realm configuration
-#
-# For those that might not understand the references in this file, the
-# definitions are all based on the classic Mel Brooks' film "Spaceballs". ;)
-# =============================================================================
+
 
 # -----------------------------------------------------------------------------
 # Users and their assigned roles
@@ -29,18 +24,17 @@
 # Each line conforms to the format defined in the
 # org.apache.shiro.realm.text.TextConfigurationRealm#setUserDefinitions JavaDoc
 # -----------------------------------------------------------------------------
+
 [users]
-# user 'root' with password 'secret' and the 'admin' role
-root = secret, admin
-# user 'guest' with the password 'guest' and the 'guest' role
-guest = guest, guest
-# user 'presidentskroob' with password '12345' ("That's the same combination on
-# my luggage!!!" ;)), and role 'president'
-presidentskroob = 12345, president
-# user 'darkhelmet' with password 'ludicrousspeed' and roles 'darklord' and 'schwartz'
-darkhelmet = ludicrousspeed, darklord, schwartz
-# user 'lonestarr' with password 'vespa' and roles 'goodguy' and 'schwartz'
-lonestarr = vespa, goodguy, schwartz
+# user = password, role1, role2, role3, ...
+
+root            = secret        , admin
+guest           = guest         , guest
+presidentskroob = 12345         , president
+darkhelmet      = ludicrousspeed, darklord, schwartz
+lonestarr       = vespa         , goodguy, schwartz
+
+
 
 # -----------------------------------------------------------------------------
 # Roles with assigned permissions
@@ -48,11 +42,11 @@ lonestarr = vespa, goodguy, schwartz
 # Each line conforms to the format defined in the
 # org.apache.shiro.realm.text.TextConfigurationRealm#setRoleDefinitions JavaDoc
 # -----------------------------------------------------------------------------
+
 [roles]
-# 'admin' role has all permissions, indicated by the wildcard '*'
+# role = perm1, perm2, perm3, ...
+
 admin = *
-# The 'schwartz' role can do anything (*) with any lightsaber:
-schwartz = lightsaber:*
-# The 'goodguy' role is allowed to 'drive' (action) the winnebago (type) with
-# license plate 'eagle5' (instance specific id)
+schwartz = com.mycompany.myapp:Customer:*,\
+           com.mycompany.myapp:Order:submit:*
 goodguy = winnebago:drive:eagle5

http://git-wip-us.apache.org/repos/asf/isis/blob/4ceaab88/core/metamodel/src/main/java/org/apache/isis/core/runtime/authentication/standard/Authenticator.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/runtime/authentication/standard/Authenticator.java b/core/metamodel/src/main/java/org/apache/isis/core/runtime/authentication/standard/Authenticator.java
index 20e9741..b8ba68b 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/runtime/authentication/standard/Authenticator.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/runtime/authentication/standard/Authenticator.java
@@ -32,14 +32,16 @@ public interface Authenticator extends ApplicationScopedComponent {
     boolean canAuthenticate(Class<? extends AuthenticationRequest> authenticationRequestClass);
 
     /**
-     * Whether this {@link Authenticator} is valid in the running context (and
-     * optionally with respect to the provided {@link AuthenticationRequest}).
+     * UNUSED ... IMPLEMENTATIONS SHOULD PROVIDE A STUB METHOD ONLY.
      * 
      * <p>
-     * For example, the <tt>ExplorationAuthenticator</tt> (in the default
-     * runtime) is only available for authentication if running in
-     * <i>exploration mode</i>.
+     * This method is only ever called from {@link AuthenticatorAbstract}, and as such should
+     * not be defined as part of the API.
+     * 
+     * <p>
+     * TODO: remove in 2.0.0 [ISIS-292]
      */
+    @Deprecated
     boolean isValid(AuthenticationRequest request);
 
     /**

http://git-wip-us.apache.org/repos/asf/isis/blob/4ceaab88/core/metamodel/src/main/java/org/apache/isis/core/runtime/authentication/standard/AuthenticatorAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/runtime/authentication/standard/AuthenticatorAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/runtime/authentication/standard/AuthenticatorAbstract.java
index 189d23d..f1d78dd 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/runtime/authentication/standard/AuthenticatorAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/runtime/authentication/standard/AuthenticatorAbstract.java
@@ -65,6 +65,20 @@ public abstract class AuthenticatorAbstract implements Authenticator {
         return new SimpleSession(request.getName(), request.getRoles(), code);
     }
 
+    /**
+     * Whether this {@link Authenticator} is valid in the running context (and
+     * optionally with respect to the provided {@link AuthenticationRequest}).
+     * 
+     * <p>
+     * For example, the <tt>ExplorationAuthenticator</tt> (in the default
+     * runtime) is only available for authentication if running in
+     * <i>exploration mode</i>.
+     * 
+     * <p>
+     * TODO: [ISIS-292] should change visibility to <tt>protected</tt> when remove from the API.
+     */
+    public abstract boolean isValid(AuthenticationRequest request);
+
     // //////////////////////////////////////////////////////
     // Injected (via constructor)
     // //////////////////////////////////////////////////////

http://git-wip-us.apache.org/repos/asf/isis/blob/4ceaab88/core/runtime/pom.xml
----------------------------------------------------------------------
diff --git a/core/runtime/pom.xml b/core/runtime/pom.xml
index 770a667..b63fe25 100644
--- a/core/runtime/pom.xml
+++ b/core/runtime/pom.xml
@@ -26,7 +26,6 @@
 		<version>1.0.1-SNAPSHOT</version>
 	</parent>
 
-	<groupId>org.apache.isis.core</groupId>
 	<artifactId>isis-core-runtime</artifactId>
 	<name>Isis Core Runtime</name>
 

http://git-wip-us.apache.org/repos/asf/isis/blob/4ceaab88/example/application/quickstart_wicket_restful_jdo/pom.xml
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/pom.xml b/example/application/quickstart_wicket_restful_jdo/pom.xml
index 3978312..f1fff7d 100644
--- a/example/application/quickstart_wicket_restful_jdo/pom.xml
+++ b/example/application/quickstart_wicket_restful_jdo/pom.xml
@@ -34,6 +34,7 @@
 		<isis-objectstore-jdo.version>1.0.0</isis-objectstore-jdo.version>
 		<isis-viewer-wicket.version>1.0.0</isis-viewer-wicket.version>
 		<isis-viewer-restfulobjects.version>1.0.0</isis-viewer-restfulobjects.version>
+		<isis-security-shiro.version>1.0.0-SNAPSHOT</isis-security-shiro.version>
 	</properties>
     
     <repositories>
@@ -190,6 +191,13 @@
 				<scope>import</scope>
 			</dependency>
 
+			<dependency>
+				<groupId>org.apache.isis.security</groupId>
+				<artifactId>isis-security-shiro</artifactId>
+				<version>${isis-security-shiro.version}</version>
+				<type>pom</type>
+				<scope>import</scope>
+			</dependency>
 
             <!-- this project's own modules -->
             <dependency>

http://git-wip-us.apache.org/repos/asf/isis/blob/4ceaab88/example/application/quickstart_wicket_restful_jdo/viewer-webapp/pom.xml
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/viewer-webapp/pom.xml b/example/application/quickstart_wicket_restful_jdo/viewer-webapp/pom.xml
index 4e47a8b..b8ef633 100644
--- a/example/application/quickstart_wicket_restful_jdo/viewer-webapp/pom.xml
+++ b/example/application/quickstart_wicket_restful_jdo/viewer-webapp/pom.xml
@@ -85,67 +85,45 @@
             <groupId>${project.groupId}</groupId>
             <artifactId>quickstart_wicket_restful_jdo-dom</artifactId>
         </dependency>
-        
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>quickstart_wicket_restful_jdo-fixture</artifactId>
         </dependency>
-
-
-        <!-- objectstore/domain service/repository implementations -->
-        
+        <!-- objectstore/domain service/repository implementations (brings in dependency to objectstore-jdo)-->
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>quickstart_wicket_restful_jdo-objstore-jdo</artifactId>
         </dependency>
         
         
-        
-
-        <!-- isis viewers -->
+        <!-- other isis components -->
 		<dependency>
 			<groupId>org.apache.isis.viewer</groupId>
 			<artifactId>isis-viewer-wicket-impl</artifactId>
 		</dependency>
-
         <dependency>
             <groupId>org.apache.isis.viewer</groupId>
             <artifactId>isis-viewer-restfulobjects-impl</artifactId>
         </dependency>
+		<dependency>
+			<groupId>org.apache.isis.security</groupId>
+			<artifactId>isis-security-shiro</artifactId>
+		</dependency>
 
 
-
-
-        <dependency>
-            <groupId>org.apache.isis.core</groupId>
-            <artifactId>isis-core-metamodel</artifactId>
-        </dependency>
+		<!-- isis core -->
         <dependency>
             <groupId>org.apache.isis.core</groupId>
             <artifactId>isis-core-runtime</artifactId>
         </dependency>
         <dependency>
             <groupId>org.apache.isis.core</groupId>
-            <artifactId>isis-core-bytecode-cglib</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.isis.core</groupId>
-            <artifactId>isis-core-objectstore</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.isis.core</groupId>
             <artifactId>isis-core-profilestore</artifactId>
         </dependency>
         <dependency>
             <groupId>org.apache.isis.core</groupId>
             <artifactId>isis-core-security</artifactId>
         </dependency>
-        <!-- 
-        <dependency>
-            <groupId>org.apache.isis.security</groupId>
-            <artifactId>isis-security-file</artifactId>
-        </dependency>
-         -->
         
         <!-- to run using WebServer (optional) -->
         <dependency>
@@ -155,17 +133,12 @@
             <optional>true</optional>
         </dependency>
 
-        <dependency>
-            <groupId>org.apache.geronimo.specs</groupId>
-            <artifactId>geronimo-servlet_2.5_spec</artifactId>
-        </dependency>
 
 
 		<!-- 
 		  JDBC drivers 
-		  (if using jdo or sql object store)
+		  (for jdo objectstore)
 		  -->
-
         <dependency>
             <groupId>org.hsqldb</groupId>
             <artifactId>hsqldb</artifactId>

http://git-wip-us.apache.org/repos/asf/isis/blob/4ceaab88/example/application/quickstart_wicket_restful_jdo/viewer-webapp/src/main/webapp/WEB-INF/isis.properties
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/viewer-webapp/src/main/webapp/WEB-INF/isis.properties b/example/application/quickstart_wicket_restful_jdo/viewer-webapp/src/main/webapp/WEB-INF/isis.properties
index 191a324..7c84ae6 100644
--- a/example/application/quickstart_wicket_restful_jdo/viewer-webapp/src/main/webapp/WEB-INF/isis.properties
+++ b/example/application/quickstart_wicket_restful_jdo/viewer-webapp/src/main/webapp/WEB-INF/isis.properties
@@ -80,7 +80,8 @@ isis.persistor=datanucleus
 # 
  
 # default is file in SERVER mode, none in SERVER_EXPLORATION.  Derived from wicket mode 
-isis.authentication=bypass
+isis.authentication=org.apache.isis.security.shiro.authentication.ShiroAuthenticationManagerInstaller
+isis.authentication.shiro.iniLocation=classpath:shiro.ini
 
 
 #

http://git-wip-us.apache.org/repos/asf/isis/blob/4ceaab88/example/application/quickstart_wicket_restful_jdo/viewer-webapp/src/main/webapp/WEB-INF/shiro.ini
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/viewer-webapp/src/main/webapp/WEB-INF/shiro.ini b/example/application/quickstart_wicket_restful_jdo/viewer-webapp/src/main/webapp/WEB-INF/shiro.ini
new file mode 100644
index 0000000..bc605c7
--- /dev/null
+++ b/example/application/quickstart_wicket_restful_jdo/viewer-webapp/src/main/webapp/WEB-INF/shiro.ini
@@ -0,0 +1,49 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#
+
+
+# -----------------------------------------------------------------------------
+# Users and their assigned roles
+#
+# Each line conforms to the format defined in the
+# org.apache.shiro.realm.text.TextConfigurationRealm#setUserDefinitions JavaDoc
+# -----------------------------------------------------------------------------
+
+[users]
+# user = password, role1, role2, role3, ...
+
+sven = pass, org.apache.isis.viewer.wicket.roles.USER, admin
+dick = pass, org.apache.isis.viewer.wicket.roles.USER, admin
+bob  = pass, org.apache.isis.viewer.wicket.roles.USER, admin
+joe  = pass, org.apache.isis.viewer.wicket.roles.USER, admin
+
+
+
+
+# -----------------------------------------------------------------------------
+# Roles with assigned permissions
+# 
+# Each line conforms to the format defined in the
+# org.apache.shiro.realm.text.TextConfigurationRealm#setRoleDefinitions JavaDoc
+# -----------------------------------------------------------------------------
+
+[roles]
+# role = perm1, perm2, perm3, ...
+
+admin = *

http://git-wip-us.apache.org/repos/asf/isis/blob/4ceaab88/example/application/quickstart_wicket_restful_jdo/viewer-webapp/src/main/webapp/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/viewer-webapp/src/main/webapp/WEB-INF/web.xml b/example/application/quickstart_wicket_restful_jdo/viewer-webapp/src/main/webapp/WEB-INF/web.xml
index b23b303..7c82c7c 100644
--- a/example/application/quickstart_wicket_restful_jdo/viewer-webapp/src/main/webapp/WEB-INF/web.xml
+++ b/example/application/quickstart_wicket_restful_jdo/viewer-webapp/src/main/webapp/WEB-INF/web.xml
@@ -21,7 +21,33 @@
     xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
 
-    <display-name>Quickstart Wicket app</display-name>
+    <display-name>Quickstart Wicket/RestfulObjects app</display-name>
+
+
+    <listener>
+        <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
+    </listener>
+
+    <filter>
+        <filter-name>ShiroFilter</filter-name>
+        <filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
+    </filter>
+
+    <filter-mapping>
+        <filter-name>ShiroFilter</filter-name>
+        <url-pattern>/*</url-pattern>
+    </filter-mapping>
+
+    <filter>
+        <filter-name>IsisShiroFilter</filter-name>
+        <filter-class>org.apache.isis.security.shiro.web.IsisShiroSecurityManagerThreadLocalBinderFilter</filter-class>
+    </filter>
+
+    <filter-mapping>
+        <filter-name>IsisShiroFilter</filter-name>
+        <url-pattern>/*</url-pattern>
+    </filter-mapping>
+