Broadcast on Broadcast off
The Documentation for Project Zero has moved. Please update your bookmarks to: http://www.projectzero.org/documentation/
Table of
Contents...
Hide

Project Zero Developer’s Guide

Concepts and components
Basic concepts overview
Event processing
Writing Java handlers
Writing Groovy handlers
Firing events
Global Context
Global Context reference
Application directory layout
Virtualized directories
Assemble
PHP
Features and configuration
Configuration
Debugging
Dependencies
Packaging
Application classpath
Logging and tracing
RESTful resources
RESTful documentation
File serving
Response rendering
Validators and validation
HTTP error handling
Calling a remote resource
Using the Connection API
Sending an email using EmailConnection
Configuring destinations
Configuring protocols
Configuring connection handlers
Creating a connection handler
Creating a custom protocol transport
Simple logging connection handlers
Protocol reference
Client programming with Dojo
Runtime options
Deployment modifications
HTTP configuration
SSL configuration
Proxy configuration
Extending the CLI
Security considerations
Authentication
OpenID authentication
Extending security
Security tokens
CSRF prevention support
Extending token support
Leveraging TAI
User service
File based user service
LDAP user service
Extending user service
Security Utilities
Leveraging XOREncoder
Extensions
Atom support
RSS support
JSON support
XMLEncoder
REST to SOAP extension
URIUtils
Developer Web tools
Database setup tools
Configuring data access
Common query patterns
Advanced query patterns
Update patterns
Local database transactions
Extending data access
Configuration vendor differences
PHP data access
Resource model
Configuring ZRM
Resource model declaration
Programmatic model API
HTTP REST API
A ZRM mini tutorial
Active content filtering support
Default filters
Custom filters
Runtime management
Management commands
Zero socket opener
Other extension modules
Amazon E-commerce service
Flickr service
WeatherZero forecast service
Wikipedia service
Reference
Zero command line interface
JavaDoc - Public API
JavaDoc - Public SPI
JavaDoc - All Classes

 

Extending user service

The Project Zero user service leverages the Global Context to make it easy to add your own user service implementation. The following sections of this article provide an example to demonstrate how you would add support for your own user service implementation.

Configuring a custom user registry

The following example shows a configuration file to register your user service implementation:


# current defaults are file and ldap
/config/security/userservice/registryType="database"
# must implement zero.core.security.userservice.UserService
/config/security/userservice/registryImpl/database="zero.example.DatabaseUserService"

This example displays a basic stanza with two attributes registryType and registryImpl/<registryType>. This provides the mapping between the registryType and the actual implementation class.

Customizing the user registry implementation

To demonstrate how this could be implemented, the code for DatabaseUserService has been provided in the following example.

package zero.example;

import java.security.Principal;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.logging.Level;
import java.util.logging.Logger;

import zero.core.security.GroupImpl;
import zero.core.security.PrincipalImpl;
import zero.core.security.userservice.UserService;
import zero.core.security.userservice.UserServiceException;
import zero.data.Manager;


public class DatabaseUserService implements UserService {
        
        private static final String CLASS_NAME = 
        DatabaseUserService.class.getCanonicalName();
        private static final Logger logger = Logger.getLogger(CLASS_NAME);
        
        public Set<Principal> getUser(String username) throws UserServiceException {
                if (logger.isLoggable(Level.FINER)) {
                        logger.entering(CLASS_NAME, "getUser","username ->" + username);
                }
                if(username == null || username.trim() == "") {
                        if (logger.isLoggable(Level.FINER)) {
                                logger.exiting(CLASS_NAME, "login",
                                "user name is null or empty, "+
                                "returning empty set of principals");
                        }
                        return new HashSet<Principal>();
                }
                Manager authDB = Manager.create("authenticationDB");
                if(authDB == null) {
                        throw new UserServiceException("failed to create DB manager");
                }
                List<Map<String, Object>> results = 
                authDB.queryList("SELECT * FROM users "+
                "WHERE username = ?", username);
                if ( results != null && (!results.isEmpty())) {
                        if (logger.isLoggable(Level.FINER)) {
                                logger.exiting(CLASS_NAME, "getUser",
                                "returning set of principals");
                        }
                        return getPrincipal (username);
                }
                else {
                        if (logger.isLoggable(Level.FINER)) {
                                logger.exiting(CLASS_NAME, "getUser",
                                "returning empty set of principals");
                        }
                        return new HashSet<Principal>();
                }
        }
        
        public Set<Principal> login(String username, String passwd)
        throws UserServiceException {
                if (logger.isLoggable(Level.FINER)) {
                        logger.entering(CLASS_NAME, 
                        "login","username ->" + username);
                }
                if(username == null || username.trim() == "") {
                        if (logger.isLoggable(Level.FINER)) {
                                logger.exiting(CLASS_NAME, "login",
                                "user name is null or empty, "+
                                "returning empty set of principals");
                        }
                        return new HashSet<Principal>();
                }
                Manager authDB = Manager.create("authenticationDB");
                if(authDB == null) {
                        throw new UserServiceException("failed to create DB manager");
                }
                List<Map<String, Object>> results = 
                authDB.queryList("SELECT * FROM users WHERE " + "" +
                "username = ? AND password = ?", 
                username, passwd);
                if ( results != null && (!results.isEmpty())) {
                        if (logger.isLoggable(Level.FINER)) {
                                logger.exiting(CLASS_NAME, "login",
                                "returning set of principals");
                        }
                        return getPrincipal (username);
                }
                else {
                        if (logger.isLoggable(Level.FINER)) {
                                logger.exiting(CLASS_NAME, "login",
                                "returning empty set of principals");
                        }
                        return new HashSet<Principal>();
                }
        }
        
        private Set<Principal> getPrincipal(String username)
        throws UserServiceException{
                if (logger.isLoggable(Level.FINER)) {
                        logger.entering(CLASS_NAME, "getPrincipal","username ->" + username);
                }
                // add user information for principal
                Set<Principal> userSet = new HashSet<Principal>();
                Principal user = new PrincipalImpl(username);
                userSet.add(user);
                
                // get group information for user
                Manager authDB = Manager.create("authenticationDB");
                if(authDB == null) {
                        throw new UserServiceException("failed to create DB manager");
                }
                List<Map<String, Object>> results =  
                authDB.queryList("SELECT * FROM usertogroupmapping " + 
                "WHERE username = ?", username);
                Set<Principal> groups = new TreeSet<Principal>();
                for (Map item : results) {
                        String groupName = (String) item.get ("groups");
                        groups.add((new GroupImpl (groupName)));
                }
                userSet.addAll(groups);
                if (logger.isLoggable(Level.FINER)) {
                        logger.exiting(CLASS_NAME, "getPrincipal",
                        "primcipal ->" + userSet);
                }
                return userSet;
        }
}

As the name indicates, the DatabaseUserService class provides a database user registry that contains user names, passwords and groups.

Using the data access extension

To leverage the data access extension that is included as part of Project Zero using a MySQL database, some additional configuration is required for the DatabaseUserService registry example. (See the Configuring data access article for more information.) The configuration stanza for this example is shown in the following example.

/config/db/authenticationDB = {
    "class" : "com.mysql.jdbc.jdbc2.optional.MysqlDataSource",
    "serverName" : "localhost",
    "portNumber" : 3306,
    "databaseName" : "authentication",
    "user" : "root",
    "password" : "root"
}

Validating the DatabaseUserService registry

The authentication database contains the following tables:
users
Contains the list of username and passwords for each user.
usertogroupmapping
Contains the list of groups each user belongs to.

Once the UserService has validated the user name and password matches that were passed to the login method, a subsequent database call is made against the usertogroupmapping table to obtain the list of groups this user belongs to.

The following example data can be used to validate the DatabaseUserService.

Current database: authentication
mysql> select * from users;

+----------+----------+
| username | password |
+----------+----------+
| user2    | pass2    |
| user1    | pass1    |
+----------+----------+
2 rows in set (0.20 sec)

mysql> select * from usertogroupmapping;
+----------+--------+
| username | groups |
+----------+--------+
| user1    | group1 |
| user1    | group2 |
| user1    | group3 |
| user2    | group3 |
+----------+--------+
4 rows in set (0.00 sec)

Securing DatabaseUserService registry resources

Securing resources is independent of the UserRegistry. To learn more about how to secure resources see the Security article.

For this example, the following stanza was used.

#Authorization rules
@include "security/rule.config"{
   "conditions": "/request/path =~ /basicauth/customers(/.*)?",
   "authType" : "Basic",
   "groups" : ["group1"]
}

r13 - 06 Feb 2008 - 16:58:27 - paynel
Syndicate this site RSS ATOM
Copyright 2007 © IBM Corporation | Privacy | Terms of Use | About this site