Introduction
Publishing server authentication is based on Apache
Shiro. For a general understanding it is highly recommended to
make yourself comfortable with the general concepts of Shiro.
When to use custom realm
Typical use case:
A content system has a built-in user management and
authentication provider. Users and roles of the content system
should be able to login to priint suite using the same user
names and passwords as in the content system.
Authentication data flow
Publishing server comes with a build-in shiro realm –
called “pubServerRealm”. This will authenticate users against
the internal pubserver repository. Never change or remove this
realm, because it is necessary for “admin” or installer/updater
access to the server.
If you add another realm authentication will try to authenticate
the user for all configured realms until a realm signals
authentication success. Authentication fails if the given login
data lead to a fail in each realm. Normally the pubServerRealm
is the last realm in the sequence.
Typically, when starting an authentication for a realm the login
input will be checked if it matches the pattern for the realm.
If it does not match the pattern the authentication fails early
for the realm and the login data are sent to the next realm in
the chain. Patterns can just be defined as regular expressions
that must match (for include or exclude). E.g. if a login string
looks like an email (e.g. “sandra@boing.eu”) it is evaluated by
another realm than a login that resembles a qualified Windows
user name (e.g. “SBS-BOING\sandra”).
How to use a custom realm
1. Implement a custom realm as a standard Java
project. As an example, use the code from the DemoRealm project.
2. Export your realm project as a jar file and copy it into
<domainDir>/lib dir.
3. Create a shiro.ini configuration in
“<domainDir>/config” and customize it to your needs.
4. Restart application server Realm changes get only visible
after a restart.
Design of a Realm Project in Java
The DemoProject contains the typical pattern for an
additional pubserver.
The core pattern is to derive a realm class from Shiro’s
AuthorizingRealm and to implement your custom stuff by
overriding the doGetAuthenticationInfo method.
After a user login is verified by your custom logic you must
assign the user to a user account within publishing server. A
user account is represented by the Serveruser class of
CometServer4SDK. This is not a part of the public API but of
CometServer4SDK but you can use for the current purpose.
Assigning is done by a synchronizeUser business method from
CometServerLight. This method also provides a possibility to
assign special pubserver roles to the user. This is supported by
the membershipMapping field of the AbstractRealmConfig class.
If the user is not already existing in publishing server then it
will be created silently in the background by synchronizeUser.
Derive your config from AbstractRealmConfig
The fields of the config class are filled in the
shiro.ini. Each field defined in your config is available in the
shiro.ini, so the information of the config can be extended by
new fields easily.
Create your own user class.
Available information about users depend on your
authentication provider, so you will most likely have to define
your own class for users, containing the information necessary
for authentication.
In your realm you need to map your user class to Serveruser for
user synchronization.
Derive your realm from AuthorizingRealm
There are two methods from interface, which must be
implemented in your custom realm.
You should create an empty implementation for
doGetAuthorizationInfo method. Authorization in pubserver is
handling on another level of the system.
You must implement the doGetAuthenticationInfo method as implied
by the interface. This is the core method we are dealing with
here.
An additional method synchronizeUser with your own User-class
should be implemented, to synchronize users into pubserver. This
method must be called in doGetAuthenticationInfo.
doGetAuthorizationInfo
Should always return null and do nothing else.
doGetAuthenticationInfo
Return null if you detect that the login is not valid
– by what means ever.
Throw an AuthenticationException if an unexpected error happens
to come up. E.g. the contact to the authentication server was
lost.
synchronizeUser
The simple magic is done by
AdminLocal adminBean =
CometServer4ServiceLocator.ServiceLocatorEnum.INSTANCE.getAdminLocal();
adminBean.synchronizeUser(serverUser, roleNames,
config.getDefaultDataset(), config.getDefaultRole());
Where config is an instance derived from AbstractRealmConfig and
serverUser is an instance of the Serveruser class representing a
user reference in publishing server.
Using shiro.ini
Configuration is done by a special ini file located in
the domain config folder.
<domainDir>\config\shiro.ini
This file is not part of a standard installation of pubserver.
In the standard installation an internal version of shiro.ini is
used.
This file is read every time when the PubServerKernel is
deployed, i.e. during a server start. This means that shiro.ini
is not monitored by the system. Changes in the file will only be
applied during a restart.
Default shiro.ini
This is the content of the default shiro.ini to start
with.
Just copy the contents into the
[main] sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager sessionDAO = org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO sessionManager.sessionDAO = $sessionDAO securityManager.sessionManager = $sessionManager cacheManager = org.apache.shiro.cache.ehcache.EhCacheManager securityManager.cacheManager = $cacheManager credentialsMatcher = org.apache.shiro.authc.credential.Md5CredentialsMatcher pubCredentialsMatcher = com.priint.pubserver.auth.realm.PubServerCredentialsMatcher pubServerAuthenticationToken = com.priint.pubserver.auth.realm.PubServerAuthenticationToken authcListener1 = com.priint.pubserver.auth.PubServerAuthenticationListener securityManager.authenticator.authenticationListeners = $authcListener1 cookie = org.apache.shiro.web.servlet.SimpleCookie cookie.name = PubServSessID cookie.path = / securityManager.sessionManager.sessionIdCookie = $cookie securityManager.sessionManager.globalSessionTimeout = 36000000 sessionListener = com.priint.pubserver.auth.PubServerSessionListener securityManager.sessionManager.sessionListeners = $sessionListener sessionValidationScheduler = org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler sessionValidationScheduler.interval = 3600000 sessionValidationScheduler.sessionManager = $sessionManager securityManager.sessionManager.sessionValidationScheduler = $sessionValidationScheduler # DEFAULT REALM pubServerRealm = com.priint.pubserver.auth.realm.PubServerRealm pubServerRealm.credentialsMatcher = $pubCredentialsMatcher # CUSTOM REALMS # add your custom realms over here # ... # attach the realms to shiro securityManager.realms = $pubServerRealm
Adding a custom realm to shiro.ini
Do not change any content before the "# CUSTOM
REALMS".
To add a new realm just put the relevant realm configuration
settings below the "# CUSTOM REALMS" and finally add the new
realm to the list of securityManager.realms. That is all.
The following is a replica of the default shiro.ini with the
addition of a DemoRealm. Additions marked in yellow.
The most important rule is: Your new realm must precede the
“pubServerRealm” when defining “securityManager.realms”. Never
remove or change “pubServerRealm”.
Add fields of config to your shiro.ini with
<realmname>.config.<fieldname>.
[main] sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager sessionDAO = org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO sessionManager.sessionDAO = $sessionDAO securityManager.sessionManager = $sessionManager cacheManager = org.apache.shiro.cache.ehcache.EhCacheManager securityManager.cacheManager = $cacheManager credentialsMatcher = org.apache.shiro.authc.credential.Md5CredentialsMatcher pubCredentialsMatcher = com.priint.pubserver.auth.realm.PubServerCredentialsMatcher pubServerAuthenticationToken = com.priint.pubserver.auth.realm.PubServerAuthenticationToken authcListener1 = com.priint.pubserver.auth.PubServerAuthenticationListener securityManager.authenticator.authenticationListeners = $authcListener1 # CUSTOM REALM pubServerRealm = com.priint.pubserver.auth.realm.PubServerRealm pubServerRealm.credentialsMatcher = $pubCredentialsMatcher # DEMO REALM demoRealm = com.priint.pubserver.auth.realm.DemoRealm demoRealm.config.url = file:///C:/devstack/workspace/demos/DemoRealm/example-users.xml demoRealm.config.defaultRole = Normal User demoRealm.config.defaultMenu = publications demoRealm.config.defaultDataset = demo demoRealm.config.membershipMapping = Tims:Administrator,Struppies:DTP-Operator demoRealm.config.includePattern = ^.+@kontoso\.com$ demoRealm.config.excludePattern = contoso\.com$ securityManager.realms = $demoRealm, $pubServerRealm # cookie for single sign on is set to PubServSessID and Root Path # so that we can access it from any web app cookie = org.apache.shiro.web.servlet.SimpleCookie cookie.name = PubServSessID cookie.path = / securityManager.sessionManager.sessionIdCookie = $cookie # Set session timeout to 36,000,000 milliseconds = 10 hours securityManager.sessionManager.globalSessionTimeout = 36000000 sessionListener = com.priint.pubserver.auth.PubServerSessionListener securityManager.sessionManager.sessionListeners = $sessionListener # Set session wrapup schedule to 3,600,000 milliseconds = 1 hours sessionValidationScheduler = org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler sessionValidationScheduler.interval = 3600000 sessionValidationScheduler.sessionManager = $sessionManager securityManager.sessionManager.sessionValidationScheduler = $sessionValidationScheduler