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

[1/6] git commit: ISIS-290: first steps towards a shiro impl

ISIS-290: first steps towards a shiro impl


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

Branch: refs/heads/master
Commit: 95c0b553b7da00724db232e58d005c1269b42487
Parents: 24563ea
Author: Dan Haywood <da...@apache.org>
Authored: Sun Dec 30 18:09:26 2012 +0000
Committer: Dan Haywood <da...@apache.org>
Committed: Fri Jan 4 09:20:05 2013 +0000

----------------------------------------------------------------------
 component/security/shiro/NOTICE                    |    7 +
 component/security/shiro/pom.xml                   |  133 ++++++++
 .../appended-resources/supplemental-models.xml     |  106 +++++++
 .../shiro/ShiroAuthenticatorOrAuthorizor.java      |  234 +++++++++++++++
 .../apache/isis/security/shiro/ShiroConstants.java |   36 +++
 .../ShiroAuthenticationManagerInstaller.java       |   44 +++
 .../ShiroAuthorizationManagerInstaller.java        |   40 +++
 component/security/shiro/src/site/apt/index.apt    |   44 +++
 component/security/shiro/src/site/apt/jottings.apt |   24 ++
 component/security/shiro/src/site/site.xml         |   41 +++
 .../security/shiro/ShiroAuthenticatorTester.java   |  149 +++++++++
 .../shiro/authorization/ShiroAuthorizorTester.java |  150 +++++++++
 .../security/shiro/src/test/resources/shiro.ini    |   58 ++++
 13 files changed, 1066 insertions(+), 0 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/95c0b553/component/security/shiro/NOTICE
----------------------------------------------------------------------
diff --git a/component/security/shiro/NOTICE b/component/security/shiro/NOTICE
new file mode 100644
index 0000000..0a76071
--- /dev/null
+++ b/component/security/shiro/NOTICE
@@ -0,0 +1,7 @@
+Apache Isis
+Copyright 2010-2012 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
+

http://git-wip-us.apache.org/repos/asf/isis/blob/95c0b553/component/security/shiro/pom.xml
----------------------------------------------------------------------
diff --git a/component/security/shiro/pom.xml b/component/security/shiro/pom.xml
new file mode 100644
index 0000000..ca2d9e8
--- /dev/null
+++ b/component/security/shiro/pom.xml
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+
+	<parent>
+		<groupId>org.apache.isis.core</groupId>
+		<artifactId>isis</artifactId>
+		<version>1.0.1-SNAPSHOT</version>
+		<relativePath>../../../core/pom.xml</relativePath>
+	</parent>
+
+	<groupId>org.apache.isis.security</groupId>
+	<artifactId>isis-security-shiro</artifactId>
+    <version>1.0.0-SNAPSHOT</version>
+
+	<name>Isis Shiro Security</name>
+
+	<properties>
+        <siteBaseDir>.</siteBaseDir>
+		<relativeUrl/>
+		<shiro.version>1.2.1</shiro.version>
+	</properties>
+
+    <!-- used in Site generation for relative references. -->
+    <url>http://isis.apache.org/${relativeUrl}</url>
+
+	<build>
+		<pluginManagement>
+			<plugins>
+                <!-- Apache Release Audit Tool -->
+                <plugin>
+                    <groupId>org.apache.rat</groupId>
+                    <artifactId>apache-rat-plugin</artifactId>
+                    <version>0.8</version>
+	                <configuration>
+	                    <excludes>
+	                    	<!-- 
+	                    	overriding inherited excludes from oia.core:isis 
+	                    	with a more specific set for this component
+	                    	 -->
+	                        <exclude>**/target/**</exclude>
+	                        <exclude>**/target-ide/**</exclude>
+
+	                        <exclude>**/*.project</exclude>
+	                        <exclude>**/.classpath</exclude>
+	                        <exclude>**/.settings/**</exclude>
+	                    </excludes>
+                    </configuration>
+	            </plugin>
+			</plugins>
+		</pluginManagement>
+	</build>
+
+    <reporting>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-project-info-reports-plugin</artifactId>
+				<version>${maven-project-info-reports-plugin}</version>
+                <inherited>false</inherited>
+                <configuration>
+                	<dependencyLocationsEnabled>false</dependencyLocationsEnabled>
+                </configuration>
+                <reportSets>
+                    <reportSet>
+                        <inherited>false</inherited>
+                        <reports>
+                            <report>dependencies</report>
+                            <report>dependency-convergence</report>
+                            <report>plugins</report>
+                            <report>summary</report>
+                        </reports>
+                    </reportSet>
+                </reportSets>
+            </plugin>
+        </plugins>
+    </reporting>
+
+    <dependencyManagement>
+    	<!-- for benefit of application developers, using scope=import -->
+    	<dependencies>
+			<dependency>
+			    <groupId>org.apache.isis.security</groupId>
+			    <artifactId>isis-security-shiro</artifactId>
+				<version>1.0.0-SNAPSHOT</version>
+			</dependency>
+    	</dependencies>
+    </dependencyManagement>
+
+	<dependencies>
+		<dependency>
+		    <groupId>org.apache.isis.core</groupId>
+		    <artifactId>isis-core-runtime</artifactId>
+		</dependency>
+		<dependency>
+		    <groupId>org.apache.isis.core</groupId>
+		    <artifactId>isis-core-unittestsupport</artifactId>
+		    <scope>test</scope>
+		</dependency>
+		<dependency>
+		    <groupId>org.apache.isis.core</groupId>
+		    <artifactId>isis-core-runtime</artifactId>
+		    <type>test-jar</type>
+		    <scope>test</scope>
+		</dependency>
+
+        <dependency>
+            <groupId>org.apache.shiro</groupId>
+            <artifactId>shiro-core</artifactId>
+            <version>${shiro.version}</version>
+        </dependency>
+
+
+	</dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/isis/blob/95c0b553/component/security/shiro/src/main/appended-resources/supplemental-models.xml
----------------------------------------------------------------------
diff --git a/component/security/shiro/src/main/appended-resources/supplemental-models.xml b/component/security/shiro/src/main/appended-resources/supplemental-models.xml
new file mode 100644
index 0000000..ecd3906
--- /dev/null
+++ b/component/security/shiro/src/main/appended-resources/supplemental-models.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 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. -->
+<supplementalDataModels xmlns="http://maven.apache.org/supplemental-model/1.0.0"
+                        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+                        xsi:schemaLocation="http://maven.apache.org/supplemental-model/1.0.0 http://maven.apache.org/xsd/supplemental-model-1.0.0.xsd">
+
+  <supplement>
+    <project>
+      <groupId>aopalliance</groupId>
+      <artifactId>aopalliance</artifactId>
+      <version>1.0</version>
+      <licenses>
+          <license>
+              <name>Public Domain</name>
+          </license>
+      </licenses>
+    </project>
+  </supplement>
+
+  <supplement>
+   	<!-- not quite sure why licenses:download-license flags this, since license info seems to be in its POM -->
+    <project>
+		<groupId>org.datanucleus</groupId>
+	    <artifactId>datanucleus-jodatime</artifactId>
+	    <version>3.1.1</version>
+          <licenses>
+			<license>
+	            <name>The Apache Software License, Version 2.0</name>
+	            <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+	        </license>
+	    </licenses>
+    </project>
+  </supplement>
+
+  <supplement>
+    <project>
+      <groupId>org.scannotation</groupId>
+      <artifactId>scannotation</artifactId>
+      <version>1.0.3</version>
+      <licenses>
+        <license>
+            <name>The Apache Software License, Version 2.0</name>
+            <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+            <distribution>repo</distribution>          
+        </license>
+      </licenses>
+    </project>
+  </supplement>
+    
+  <supplement>
+    <project>
+      <groupId>dom4j</groupId>
+      <artifactId>dom4j</artifactId>
+      <version>1.6.1</version>
+      <licenses>
+        <license>
+            <name>BSD License</name>
+            <url>http://dom4j.sourceforge.net/dom4j-1.6.1/license.html</url>
+            <distribution>repo</distribution>          
+        </license>
+      </licenses>
+    </project>
+  </supplement>
+
+  <supplement>
+    <project>
+      <groupId>net.jcip</groupId>
+      <artifactId>jcip-annotations</artifactId>
+      <version>1.0</version>
+      <licenses>
+        <license>
+            <name>Creative Commons Attribution 2.5 License</name>
+            <url>http://creativecommons.org/licenses/by/2.5/</url>
+            <distribution>repo</distribution>          
+        </license>
+      </licenses>
+    </project>
+  </supplement>
+  
+
+  <supplement>
+    <project>
+      <groupId>xalan</groupId>
+      <artifactId>xalan</artifactId>
+      <version>2.7.0</version>
+      <licenses>
+        <license>
+            <name>The Apache Software License, Version 2.0</name>
+            <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+            <distribution>repo</distribution>          
+        </license>
+      </licenses>
+    </project>
+  </supplement>
+
+ 
+</supplementalDataModels>

http://git-wip-us.apache.org/repos/asf/isis/blob/95c0b553/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
new file mode 100644
index 0000000..c31e663
--- /dev/null
+++ b/component/security/shiro/src/main/java/org/apache/isis/security/shiro/ShiroAuthenticatorOrAuthorizor.java
@@ -0,0 +1,234 @@
+/*
+ *  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 java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+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.AuthenticationManagerInstaller;
+import org.apache.isis.core.runtime.authentication.AuthenticationRequest;
+import org.apache.isis.core.runtime.authentication.AuthenticationRequestPassword;
+import org.apache.isis.core.runtime.authentication.standard.Authenticator;
+import org.apache.isis.core.runtime.authentication.standard.SimpleSession;
+import org.apache.isis.core.runtime.authorization.AuthorizationManagerInstaller;
+import org.apache.isis.core.runtime.authorization.standard.Authorizor;
+import org.apache.log4j.Logger;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.UnavailableSecurityManagerException;
+import org.apache.shiro.authc.AuthenticationException;
+import org.apache.shiro.authc.AuthenticationInfo;
+import org.apache.shiro.authc.AuthenticationToken;
+import org.apache.shiro.authc.ExcessiveAttemptsException;
+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.AuthorizationInfo;
+import org.apache.shiro.config.IniSecurityManagerFactory;
+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.Subject;
+import org.apache.shiro.util.Factory;
+
+import com.google.common.collect.Lists;
+
+/**
+ * If Shiro is configured for both {@link AuthenticationManagerInstaller authentication} and
+ * {@link AuthorizationManagerInstaller authorization} (as recommended), then this class is
+ * 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}.
+ */
+public class ShiroAuthenticatorOrAuthorizor implements Authenticator, Authorizor {
+
+    private static final Logger LOG = Logger.getLogger(ShiroAuthenticatorOrAuthorizor.class);
+
+    private final IsisConfiguration configuration;
+
+    private SecurityManager shiroSecurityManager;
+    /**
+     * Downcast of {@link #shiroSecurityManager} (if of this type).
+     */
+    private RealmSecurityManager realmSecurityManager;
+
+    // //////////////////////////////////////////////////////
+    // constructor
+    // //////////////////////////////////////////////////////
+
+    public ShiroAuthenticatorOrAuthorizor(final IsisConfiguration configuration) {
+        this.configuration = configuration;
+    }
+
+    // //////////////////////////////////////////////////////
+    // init, shutdown
+    // //////////////////////////////////////////////////////
+
+    @Override
+    public void init() {
+        this.shiroSecurityManager = getSecurityManager(configuration);
+        if(shiroSecurityManager instanceof RealmSecurityManager) {
+            this.realmSecurityManager = (RealmSecurityManager) shiroSecurityManager;
+        }
+    }
+
+    /**
+     * The {@link SecurityManager} is shared between both the {@link Authenticator} and the {@link Authorizor}
+     * (if shiro is configured for both components).
+     */
+    private static synchronized SecurityManager getSecurityManager(final IsisConfiguration configuration) {
+        try {
+            return (DefaultSecurityManager) SecurityUtils.getSecurityManager();
+        } catch(UnavailableSecurityManagerException ex) {
+            Factory<SecurityManager> factory = new IniSecurityManagerFactory(configuration.getString("isis.security.shiro.iniLocation", "classpath:shiro.ini"));
+            SecurityManager securityManager = factory.getInstance();
+            SecurityUtils.setSecurityManager(securityManager);
+            return securityManager;
+        }
+    }
+
+    @Override
+    public void shutdown() {
+        //
+    }
+
+    // //////////////////////////////////////////////////////
+    // Authenticator API
+    // //////////////////////////////////////////////////////
+
+    @Override
+    public final boolean canAuthenticate(final Class<? extends AuthenticationRequest> authenticationRequestClass) {
+        return AuthenticationRequestPassword.class.isAssignableFrom(authenticationRequestClass);
+    }
+
+    @Override
+    public AuthenticationSession authenticate(final AuthenticationRequest request, final String code) {
+        final AuthenticationToken token = asAuthenticationToken(request);
+        
+        Subject currentUser = SecurityUtils.getSubject();
+        if(currentUser.isAuthenticated()) {
+            // TODO: verify the code passed in that this session is still alive?
+            
+            // TODO: perhaps we should cache Isis' AuthenticationSession inside the Shiro Session, and
+            // just retrieve it?
+            
+            // for now, just log them out.
+            currentUser.logout();
+        }
+        try {
+            currentUser.login(token);
+        } catch ( UnknownAccountException uae ) { 
+            LOG.debug("Unable to authenticate", uae);
+            return null;
+        } catch ( IncorrectCredentialsException ice ) {
+            LOG.debug("Unable to authenticate", ice);
+            return null;
+        } catch ( LockedAccountException lae ) {
+            LOG.info("Unable to authenticate", lae);
+            return null;
+        } catch ( ExcessiveAttemptsException eae ) { 
+            LOG.info("Unable to authenticate", eae);
+            return null;
+        } catch ( AuthenticationException ae ) {
+            LOG.error("Unable to authenticate", ae);
+            return null;
+        }
+        
+        List<String> roles = getRoles(token);
+        
+        return new SimpleSession(request.getName(), roles, code);
+    }
+
+    private List<String> getRoles(final AuthenticationToken token) {
+        if(realmSecurityManager == null) {
+            return Collections.emptyList();
+        }
+        final List<String> roles = Lists.newArrayList();
+        final Collection<Realm> realms = realmSecurityManager.getRealms();
+        for (final Realm realm : realms) {
+            if(realm.supports(token)) {
+                continue;
+            }
+            final AuthenticationInfo authenticationInfo = realm.getAuthenticationInfo(token);
+            if(authenticationInfo instanceof AuthorizationInfo) {
+                final AuthorizationInfo authorizationInfo = (AuthorizationInfo) authenticationInfo;
+                final Collection<String> realmRoles = authorizationInfo.getRoles();
+                for (final String role : realmRoles) {
+                    roles.add(realm.getName() + ":" + role);
+                }
+            }
+        }
+        return roles;
+    }
+
+    private static AuthenticationToken asAuthenticationToken(final AuthenticationRequest request) {
+        final AuthenticationRequestPassword passwordRequest = (AuthenticationRequestPassword) request;
+        final String username = passwordRequest.getName();
+        final String password = passwordRequest.getPassword();
+        
+        return new UsernamePasswordToken(username, password);
+    }
+
+
+    // //////////////////////////////////////////////////////
+    // Authorizor API
+    // //////////////////////////////////////////////////////
+
+    @Override
+    public boolean isVisibleInAnyRole(Identifier identifier) {
+        return false;
+    }
+
+    @Override
+    public boolean isUsableInAnyRole(Identifier identifier) {
+        return false;
+    }
+
+    @Override
+    public boolean isVisibleInRole(String role, Identifier identifier) {
+        if(shiroSecurityManager instanceof RealmSecurityManager) {
+            
+        }
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean isUsableInRole(String role, Identifier identifier) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    
+    // //////////////////////////////////////////////////////
+    // Injected (via constructor)
+    // //////////////////////////////////////////////////////
+
+    public IsisConfiguration getConfiguration() {
+        return configuration;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/95c0b553/component/security/shiro/src/main/java/org/apache/isis/security/shiro/ShiroConstants.java
----------------------------------------------------------------------
diff --git a/component/security/shiro/src/main/java/org/apache/isis/security/shiro/ShiroConstants.java b/component/security/shiro/src/main/java/org/apache/isis/security/shiro/ShiroConstants.java
new file mode 100644
index 0000000..d5d0d51
--- /dev/null
+++ b/component/security/shiro/src/main/java/org/apache/isis/security/shiro/ShiroConstants.java
@@ -0,0 +1,36 @@
+/*
+ *  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.ConfigurationConstants;
+import org.apache.isis.core.runtime.authentication.AuthenticationManagerInstaller;
+import org.apache.isis.core.runtime.authorization.AuthorizationManagerInstaller;
+import org.apache.isis.security.shiro.authentication.ShiroAuthenticationManagerInstaller;
+import org.apache.isis.security.shiro.authorization.ShiroAuthorizationManagerInstaller;
+
+public final class ShiroConstants {
+
+    public static final String ROOT_AUTHENTICATION = ConfigurationConstants.ROOT + AuthenticationManagerInstaller.TYPE + "." + ShiroAuthenticationManagerInstaller.NAME + ".";
+    private static final String ROOT_AUTHORIZATION = ConfigurationConstants.ROOT + AuthorizationManagerInstaller.TYPE + "." + ShiroAuthorizationManagerInstaller.NAME + ".";
+
+    private ShiroConstants() {
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/95c0b553/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
new file mode 100644
index 0000000..b462614
--- /dev/null
+++ b/component/security/shiro/src/main/java/org/apache/isis/security/shiro/authentication/ShiroAuthenticationManagerInstaller.java
@@ -0,0 +1,44 @@
+/*
+ *  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.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;
+
+public class ShiroAuthenticationManagerInstaller extends AuthenticationManagerStandardInstallerAbstractForDfltRuntime {
+
+    public static String NAME = "shiro";
+
+    public ShiroAuthenticationManagerInstaller() {
+        super(NAME);
+    }
+
+    @Override
+    protected List<Authenticator> createAuthenticators(final IsisConfiguration configuration) {
+        return Lists.<Authenticator> newArrayList(new ShiroAuthenticatorOrAuthorizor(configuration));
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/95c0b553/component/security/shiro/src/main/java/org/apache/isis/security/shiro/authorization/ShiroAuthorizationManagerInstaller.java
----------------------------------------------------------------------
diff --git a/component/security/shiro/src/main/java/org/apache/isis/security/shiro/authorization/ShiroAuthorizationManagerInstaller.java b/component/security/shiro/src/main/java/org/apache/isis/security/shiro/authorization/ShiroAuthorizationManagerInstaller.java
new file mode 100644
index 0000000..2858813
--- /dev/null
+++ b/component/security/shiro/src/main/java/org/apache/isis/security/shiro/authorization/ShiroAuthorizationManagerInstaller.java
@@ -0,0 +1,40 @@
+/*
+ *  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.authorization.standard.AuthorizationManagerStandardInstallerAbstract;
+import org.apache.isis.core.runtime.authorization.standard.Authorizor;
+import org.apache.isis.security.shiro.ShiroAuthenticatorOrAuthorizor;
+
+public class ShiroAuthorizationManagerInstaller extends AuthorizationManagerStandardInstallerAbstract {
+
+    public static String NAME = "shiro";
+
+    public ShiroAuthorizationManagerInstaller() {
+        super(NAME);
+    }
+
+    @Override
+    protected Authorizor createAuthorizor(final IsisConfiguration configuration) {
+        return new ShiroAuthenticatorOrAuthorizor(configuration);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/95c0b553/component/security/shiro/src/site/apt/index.apt
----------------------------------------------------------------------
diff --git a/component/security/shiro/src/site/apt/index.apt b/component/security/shiro/src/site/apt/index.apt
new file mode 100644
index 0000000..8978117
--- /dev/null
+++ b/component/security/shiro/src/site/apt/index.apt
@@ -0,0 +1,44 @@
+~~  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.
+
+
+
+Security LDAP Implementation
+
+ The <ldap security> module provides an implementation of Isis' authentication and
+ authorization APIs where credentials are stored in a well-known LDAP server.
+ 
+ This makes the LDAP security implementation suitable for deployment where an
+ LDAP exists.  Optionally it may be combined with other implementations (for example
+ the authorization might be performed using the file-based implementation).
+ 
+ See the security 
+ {{{../docbkx/html/guide/isis-security.html}HTML}} or 
+ {{{../docbkx/pdf/isis-security.pdf}PDF}} documentation for more detail.
+ 
+Alternatives
+
+  Alternatives include:
+  
+  * the {{{../dflt/index.html}default}} (no-op) security implementation, for prototyping use only
+
+  * the {{{../file/index.html}file-based}} security (reading from simple flat files)
+
+  * the {{{../sql/index.html}SQL}} security (reading from simple SQL tables)
+
+  []
+  

http://git-wip-us.apache.org/repos/asf/isis/blob/95c0b553/component/security/shiro/src/site/apt/jottings.apt
----------------------------------------------------------------------
diff --git a/component/security/shiro/src/site/apt/jottings.apt b/component/security/shiro/src/site/apt/jottings.apt
new file mode 100644
index 0000000..c5d1200
--- /dev/null
+++ b/component/security/shiro/src/site/apt/jottings.apt
@@ -0,0 +1,24 @@
+~~  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.
+
+
+
+Jottings
+ 
+  This page is to capture any random jottings relating to this module prior 
+  to being moved into formal documentation. 
+ 

http://git-wip-us.apache.org/repos/asf/isis/blob/95c0b553/component/security/shiro/src/site/site.xml
----------------------------------------------------------------------
diff --git a/component/security/shiro/src/site/site.xml b/component/security/shiro/src/site/site.xml
new file mode 100644
index 0000000..1f465f4
--- /dev/null
+++ b/component/security/shiro/src/site/site.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<project>
+
+	<body>
+		<breadcrumbs>
+			<item name="LDAP" href="index.html"/>
+		</breadcrumbs>
+
+		<menu name="LDAP Security">
+			<item name="About" href="index.html" />
+            <item name="Jottings" href="jottings.html" />
+		</menu>
+
+        <menu name="Security Modules">
+            <item name="Default (No-op)" href="../dflt/index.html" />
+            <item name="File" href="../file/index.html" />
+            <item name="LDAP" href="../ldap/index.html" />
+            <item name="SQL" href="../sql/index.html" />
+        </menu>
+
+        <menu name="Maven Reports" ref="reports" />
+	</body>
+</project>

http://git-wip-us.apache.org/repos/asf/isis/blob/95c0b553/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
new file mode 100644
index 0000000..f7fade1
--- /dev/null
+++ b/component/security/shiro/src/test/java/org/apache/isis/security/shiro/ShiroAuthenticatorTester.java
@@ -0,0 +1,149 @@
+/*
+ *  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/95c0b553/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
new file mode 100644
index 0000000..b1fc4dc
--- /dev/null
+++ b/component/security/shiro/src/test/java/org/apache/isis/security/shiro/authorization/ShiroAuthorizorTester.java
@@ -0,0 +1,150 @@
+/*
+ *  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/95c0b553/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
new file mode 100644
index 0000000..adca38c
--- /dev/null
+++ b/component/security/shiro/src/test/resources/shiro.ini
@@ -0,0 +1,58 @@
+#
+# 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.
+#
+# =============================================================================
+# 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
+#
+# 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
+
+# -----------------------------------------------------------------------------
+# Roles with assigned permissions
+# 
+# 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 '*'
+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)
+goodguy = winnebago:drive:eagle5