Back to Main Page
Apache Causeway is a Java framework for creating web applications using the Naked Objects pattern.
In this tutorial, we’ll explore how to add the Apache Causeway SecMan Extension, which provides an UI to manage application users, roles and their permissions within the application.
For an introduction to Apache Causeway refer to the documents at the official site https://causeway.apache.org.
Note
|
We use lombok (https://projectlombok.org/) annotations through out this tutorial. If you are not familiar with these yet, just ignore them as these are optional anyway. |
We start by reusing what we have created in the previous tutorial:
Now let’s add Maven dependencies for Shiro and SecMan:
<!-- SHIRO INTEGRATION -->
<dependency>
<groupId>org.apache.causeway.security</groupId>
<artifactId>causeway-security-shiro</artifactId>
<scope>provided</scope>
</dependency>
<!-- SECMAN POWERED BY JPA -->
<dependency>
<groupId>org.apache.causeway.extensions</groupId>
<artifactId>causeway-extensions-secman-model</artifactId>
</dependency>
<dependency>
<groupId>org.apache.causeway.extensions</groupId>
<artifactId>causeway-extensions-secman-encryption-jbcrypt</artifactId>
</dependency>
<dependency>
<groupId>org.apache.causeway.extensions</groupId>
<artifactId>causeway-extensions-secman-persistence-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.apache.causeway.extensions</groupId>
<artifactId>causeway-extensions-secman-shiro-realm</artifactId>
</dependency>
For this tutorial we are using Apache Shiro as the Security Backend. Lets add a Shiro configuration:
[main]
authenticationStrategy=org.apache.causeway.extensions.secman.delegated.shiro.realm.AuthenticationStrategyForSecMan
causewayModuleSecurityRealm=org.apache.causeway.extensions.secman.delegated.shiro.realm.CausewayModuleExtSecmanShiroRealm
securityManager.authenticator.authenticationStrategy = $authenticationStrategy
securityManager.realms = $causewayModuleSecurityRealm
[users]
[roles]
SecMan provides a bunch of menu entries, lets integrate these with our menubar layout. With this tutorial we put these into the secondary and tertiary menus.
...
<mb3:secondary>
...
<mb3:menu>
<mb3:named>Security</mb3:named>
<mb3:section>
<mb3:serviceAction objectType="causeway.ext.secman.ApplicationRoleMenu" id="allRoles">
<cpt:named>All Roles</cpt:named>
</mb3:serviceAction>
<mb3:serviceAction objectType="causeway.ext.secman.ApplicationRoleMenu" id="newRole">
<cpt:named>New Role</cpt:named>
</mb3:serviceAction>
<mb3:serviceAction objectType="causeway.ext.secman.ApplicationRoleMenu" id="findRoles">
<cpt:named>Find Roles</cpt:named>
</mb3:serviceAction>
</mb3:section>
<mb3:section>
<mb3:serviceAction objectType="causeway.ext.secman.ApplicationTenancyMenu" id="newTenancy">
<cpt:named>New Tenancy</cpt:named>
</mb3:serviceAction>
<mb3:serviceAction objectType="causeway.ext.secman.ApplicationTenancyMenu" id="findTenancies">
<cpt:named>Find Tenancies</cpt:named>
</mb3:serviceAction>
<mb3:serviceAction objectType="causeway.ext.secman.ApplicationTenancyMenu" id="allTenancies">
<cpt:named>All Tenancies</cpt:named>
</mb3:serviceAction>
</mb3:section>
<mb3:section>
<mb3:serviceAction objectType="causeway.ext.secman.ApplicationPermissionMenu" id="findOrphanedPermissions">
<cpt:named>Find Orphaned Permissions</cpt:named>
</mb3:serviceAction>
<mb3:serviceAction objectType="causeway.ext.secman.ApplicationPermissionMenu" id="allPermissions">
<cpt:named>All Permissions</cpt:named>
</mb3:serviceAction>
</mb3:section>
<mb3:section>
<mb3:serviceAction objectType="causeway.ext.secman.ApplicationFeatureViewModels" id="allProperties">
<cpt:named>All Properties</cpt:named>
</mb3:serviceAction>
<mb3:serviceAction objectType="causeway.ext.secman.ApplicationFeatureViewModels" id="allClasses">
<cpt:named>All Classes</cpt:named>
</mb3:serviceAction>
<mb3:serviceAction objectType="causeway.ext.secman.ApplicationFeatureViewModels" id="allPackages">
<cpt:named>All Packages</cpt:named>
</mb3:serviceAction>
<mb3:serviceAction objectType="causeway.ext.secman.ApplicationFeatureViewModels" id="allActions">
<cpt:named>All Actions</cpt:named>
</mb3:serviceAction>
<mb3:serviceAction objectType="causeway.ext.secman.ApplicationFeatureViewModels" id="allCollections">
<cpt:named>All Collections</cpt:named>
</mb3:serviceAction>
</mb3:section>
<mb3:section>
<mb3:serviceAction objectType="causeway.ext.secman.ApplicationUserMenu" id="findUsers">
<cpt:named>Find Users</cpt:named>
</mb3:serviceAction>
<mb3:serviceAction objectType="causeway.ext.secman.ApplicationUserMenu" id="newLocalUser">
<cpt:named>New Local User</cpt:named>
</mb3:serviceAction>
<mb3:serviceAction objectType="causeway.ext.secman.ApplicationUserMenu" id="allUsers">
<cpt:named>All Users</cpt:named>
</mb3:serviceAction>
<mb3:serviceAction objectType="causeway.ext.secman.ApplicationUserMenu" id="newDelegateUser">
<cpt:named>New Delegate User</cpt:named>
</mb3:serviceAction>
</mb3:section>
</mb3:menu>
...
</mb3:secondary>
<mb3:tertiary>
<mb3:menu>
<mb3:named>Configuration Menu</mb3:named>
<mb3:section>
<mb3:serviceAction objectType="causeway.ext.secman.MeService" id="me"/>
...
</mb3:section>
</mb3:menu>
...
</mb3:tertiary>
...
Now let’s wire everything up by importing required modules into the main Application class:
@SpringBootApplication
@Import({
CausewayModuleCoreRuntimeServices.class, // Apache Causeway Runtime
CausewayModuleJpaEclipselink.class, // EclipseLink as JPA provider for Spring Data
CausewayModuleExtModelAnnotation.class, // @Model support
CausewayModuleViewerWicketViewer.class, // UI (Wicket Viewer)
CausewayModuleTestingH2ConsoleUi.class, // enables the H2 console menu item
CausewayModuleSecurityShiro.class, // Security using Shiro
// Security Manager Extension (SecMan) (1)
CausewayModuleExtSecmanModel.class,
CausewayModuleExtSecmanRealmShiro.class,
CausewayModuleExtSecmanPersistenceJpa.class,
CausewayModuleExtSecmanEncryptionJbcrypt.class,
// Default Admin/User/Role Seeding Support for SecMan (2)
CausewayModuleTestingFixturesApplib.class,
})
@EntityScan(basePackageClasses = { // (3)
Employee.class,
})
public class Application {
...
@Bean
public SecurityModuleConfig securityModuleConfigBean() { // (4)
return SecurityModuleConfig.builder()
.adminUserName("sven")
.adminAdditionalPackagePermission("org.apache.causeway")
.build();
}
@Bean
public PermissionsEvaluationService permissionsEvaluationService() { // (5)
return new PermissionsEvaluationServiceAllowBeatsVeto();
}
}
-
Required modules for SecMan to use JPA as the persistence provider and jbcrypt as encryption technology.
-
Required module for SecMan to seed the permission database with initial users, roles and permissions.
-
Explicitly tells Spring where to find JPA entities.
-
Configures which permission database entries should be seeded initially (on application startup).
-
Configures the permission policy to use, in our case allow beats veto. You can have it the other way around, if desired, or plug in your custom solution.
In this article, we switched on Shiro as security backend and extended the application to use SecMan.
The code is available on GitHub.