Changeset 6425


Ignore:
Timestamp:
Feb 26, 2014, 11:33:37 AM (9 years ago)
Author:
Nicklas Nordborg
Message:

References #1599: Convert authentication plug-in system to an extension point

Re-designed the authentication process a bit to make it possible to return more information about the authentication back to the core.

Authentication managers should now return a AutheniticatedUser object instead of AuthenticationInformation (which is deprecated).

Introduced AuthenticationMethod which is stored in the SessionControl for potential use by client applications to allow/disallow user actions based on the authentication method used.

Introduced ExtraUserInformation which also allow extended properties to be synchronized with user accounts.

Location:
trunk/src/core/net/sf/basedb/core
Files:
3 added
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/core/net/sf/basedb/core/AuthenticationContext.java

    r6423 r6425  
    2222package net.sf.basedb.core;
    2323
    24 import net.sf.basedb.core.authentication.AuthenticationInformation;
     24import net.sf.basedb.core.authentication.AuthenticatedUser;
    2525import net.sf.basedb.core.authentication.LoginRequest;
    2626import net.sf.basedb.core.data.UserData;
     
    9090  }
    9191 
     92  /**
     93    Load a user item from the BASE database given an internal id.
     94    @param id The internal id for the user
     95    @return A UserData object or null if there is no user
     96  */
     97  public UserData getUserById(int id)
     98  {
     99    return HibernateUtil.loadData(session, UserData.class, id);
     100  }
    92101 
    93102  /**
     
    95104    internal authentication.
    96105  */
    97   public AuthenticationInformation verifyUserInternal(LoginRequest loginRequest)
     106  public AuthenticatedUser verifyUserInternal(LoginRequest loginRequest)
    98107  {
    99     UserData userData = getSessionControl().verifyUserInternal(session, loginRequest);
    100     AuthenticationInformation info = new AuthenticationInformation(userData.getLogin(), userData.getExternalId());
    101     return info;   
     108    return getSessionControl().verifyUserInternal(session, loginRequest);
    102109  }
    103110
  • trunk/src/core/net/sf/basedb/core/SessionControl.java

    r6424 r6425  
    4545import net.sf.basedb.util.extensions.Registry;
    4646import net.sf.basedb.util.extensions.manager.ExtensionsManager;
     47import net.sf.basedb.core.authentication.AuthenticatedUser;
    4748import net.sf.basedb.core.authentication.AuthenticationManager;
    48 import net.sf.basedb.core.authentication.AuthenticationInformation;
     49import net.sf.basedb.core.authentication.AuthenticationMethod;
     50import net.sf.basedb.core.authentication.ExtraUserInformation;
    4951import net.sf.basedb.core.authentication.LoginRequest;
    5052
     
    5961import java.util.Collections;
    6062import java.util.List;
     63
    6164
    6265/**
     
    378381      tx = HibernateUtil.newTransaction(session);
    379382
    380       UserData userData = null;
    381383      // Try external authentication at first, except...
    382384      // ...root user should always use internal verification
     
    384386      assert root != null : "root == null";
    385387     
     388      AuthenticatedUser authUser = null;
    386389      if (!loginRequest.getLogin().equals(root.getLogin()))
    387390      {
    388         userData = verifyUserExternal(session, loginRequest);
     391        authUser = verifyUserExternal(session, loginRequest);
    389392      }
    390393     
    391       if (userData == null)
     394      if (authUser == null)
    392395      {
    393396        // If no user was found, use internal authentication
    394         userData = verifyUserInternal(session, loginRequest);
     397        authUser = verifyUserInternal(session, loginRequest);
    395398      }
    396399     
    397       LoginInfo li = createLoginInfo(session, userData, loginRequest.getComment(), false);
     400      UserData user = HibernateUtil.loadData(session, UserData.class, authUser.getInternalId());
     401     
     402      LoginInfo li = createLoginInfo(session, user, loginRequest.getComment(), false, authUser.getAuthenticationMethod());
    398403      HibernateUtil.commit(tx);
    399404      currentContexts.clear();
     
    415420    Verify the user with internal authentication.
    416421  */
    417   UserData verifyUserInternal(org.hibernate.Session session, LoginRequest loginRequest)
     422  AuthenticatedUser verifyUserInternal(org.hibernate.Session session, LoginRequest loginRequest)
    418423  {
    419424    String login = loginRequest.getLogin();
     
    453458    }
    454459   
    455     return userData;
     460    return new AuthenticatedUser(AuthenticationMethod.INTERNAL, userData);
    456461  }
    457462 
     
    460465  */
    461466  @SuppressWarnings("unchecked")
    462   private UserData verifyUserExternal(org.hibernate.Session session, LoginRequest loginRequest)
     467  private AuthenticatedUser verifyUserExternal(org.hibernate.Session session, LoginRequest loginRequest)
    463468  {
    464469    AuthenticationContext context = new AuthenticationContext(this, session, loginRequest);
     
    468473    ExtensionsInvoker<AuthenticationManager> invoker = (ExtensionsInvoker<AuthenticationManager>)registry.useExtensions(context, xtManager.getSettings(), "net.sf.basedb.core.authentication-manager");
    469474   
    470     AuthenticationInformation info = null;
    471     boolean extraInfo = false;
     475    AuthenticatedUser authUser = null;
    472476    try
    473477    {
     
    476480      for (AuthenticationManager auth : invoker)
    477481      {
    478         info = auth.authenticate();
    479         if (info != null)
     482        authUser = auth.authenticate();
     483        if (authUser != null)
    480484        {
    481485          // Found a valid login
    482           extraInfo = auth.supportsExtraInformation() && info.hasExtraInfo;
    483486          break;
    484487        }
     
    506509   
    507510    // Return null to force internal verification
    508     if (info == null) return null;
    509 
    510     // Load user information, first try 'id' and then 'login'
    511     UserData userData = context.getUserByExternalId(info.id);
    512     if (userData == null)
    513     {
    514       userData = context.getUserByLogin(info.login);
    515     }
     511    if (authUser == null) return null;
     512
     513   
     514    // Load user information, priority order is 'internal id', 'external id', 'login'
     515    UserData userData = null;
     516    if (authUser.getInternalId() > 0)
     517    {
     518      userData = HibernateUtil.loadData(session, UserData.class, authUser.getInternalId());
     519    }
     520    if (userData == null && authUser.getExternalId() != null)
     521    {
     522      userData = context.getUserByExternalId(authUser.getExternalId());
     523    }
     524    if (userData == null && authUser.getLogin() != null)
     525    {
     526      userData = context.getUserByLogin(authUser.getLogin());
     527    }
     528     
    516529    if (userData == null)
    517530    {
    518531      // Create new user
    519532      userData = new UserData();
    520       userData.setExternalId(info.id);
    521       userData.setLogin(info.login);
    522       userData.setName(info.name == null ? info.login : info.name);
     533      userData.setExternalId(authUser.getExternalId());
     534      userData.setLogin(authUser.getLogin());
     535      userData.setName(authUser.getLogin());
    523536      userData.setQuota(HibernateUtil.loadData(session, QuotaData.class, SystemItems.getId(Quota.DEFAULT)));
    524537      User.addDefultRolesAndGroups(session, userData);
     
    534547   
    535548    // Synchronize extra information if supported and allowed by config
    536     if (extraInfo && (Config.getBoolean("auth.synchronize") || userData.getId() == 0))
    537     {
    538       userData.setName(info.name == null ? info.login : info.name);
    539       userData.setOrganisation(info.organisation);
    540       userData.setAddress(info.address);
    541       userData.setPhone(info.phone);
    542       userData.setFax(info.fax);
    543       userData.setEmail(info.email);
    544       userData.setUrl(info.url);
    545       userData.setDescription(info.description);
     549    if (authUser.hasExtraInformation() && (Config.getBoolean("auth.synchronize") || userData.getId() == 0))
     550    {
     551      ExtraUserInformation extraInfo = authUser.getExtraInformation();
     552      if (extraInfo.getName() != null)
     553      {
     554        userData.setName(extraInfo.getName());
     555      }
     556      userData.setOrganisation(extraInfo.getOrganisation());
     557      userData.setAddress(extraInfo.getAddress());
     558      userData.setPhone(extraInfo.getPhone());
     559      userData.setFax(extraInfo.getFax());
     560      userData.setEmail(extraInfo.getEmail());
     561      userData.setUrl(extraInfo.getUrl());
     562      userData.setDescription(extraInfo.getDescription());
     563     
     564      List<ExtendedProperty> properties = ExtendedProperties.getProperties("UserData");
     565      if (properties != null)
     566      {
     567        for (ExtendedProperty ep : properties)
     568        {
     569          Object value = extraInfo.getExtended(ep.getName());
     570          if (value == null || ep.getType().isCorrectType(value))
     571          {
     572            userData.setExtended(ep.getName(), value);
     573          }
     574        }
     575      }
    546576    }
    547577    if (userData.getId() == 0)
     
    550580    }
    551581    HibernateUtil.flush(session);
    552     return userData;
     582    return new AuthenticatedUser(authUser.getAuthenticationMethod(), userData);
    553583  }
    554584
     
    585615      // Load user data
    586616      UserData userData = HibernateUtil.loadData(session, UserData.class, userId);
    587       LoginInfo li = createLoginInfo(session, userData, comment, true);
     617      LoginInfo li = createLoginInfo(session, userData, comment, true, getAuthenticationMethod());
    588618      HibernateUtil.commit(tx);
    589619      SessionControl impersonated = Application.newSessionControl(getExternalClientId(), getRemoteId(), null);
     
    618648    Create a LoginInfo object and load all information that it needs.
    619649  */
    620   private LoginInfo createLoginInfo(org.hibernate.Session session, UserData userData, String comment, boolean impersonated)
     650  private LoginInfo createLoginInfo(org.hibernate.Session session, UserData userData, String comment, boolean impersonated, AuthenticationMethod authenticationMethod)
    621651    throws BaseException
    622652  {
     
    663693    li.userId = userData.getId();
    664694    li.userLogin = userData.getLogin();
     695    li.authenticationMethod = authenticationMethod;
    665696    li.sessionSettings = Collections.synchronizedMap(new HashMap<String,Object>());
    666697    return li;
     
    743774    updateLastAccess();
    744775    return loginInfo == null ? 0 : loginInfo.userId;
     776  }
     777 
     778  /**
     779    Get the method that was used to authenticate the currently
     780    logged in user. Internal authentication return
     781    {@link AuthenticationMethod#INTERNAL}.
     782    @return An AuthenticationMethod object or null if no user is logged in
     783    @since 3.3
     784  */
     785  public AuthenticationMethod getAuthenticationMethod()
     786  {
     787    return loginInfo == null ? null : loginInfo.authenticationMethod;
    745788  }
    746789
     
    21522195   
    21532196    /**
     2197      The authentication method used to allow the user to
     2198      login.
     2199    */
     2200    private AuthenticationMethod authenticationMethod;
     2201   
     2202    /**
    21542203      The id of the {@link ProjectData} object of the active project.
    21552204    */
  • trunk/src/core/net/sf/basedb/core/authentication/AuthenticationInformation.java

    r6424 r6425  
    2525/**
    2626  Objects of this class are returned by the
    27   {@link AuthenticationManager#authenticate()}
     27  {@link Authenticator#authenticate(String, String)}
    2828  method and contains information about the authenticated
    2929  user. The only required fields are {@link #id} and {@link #login}.
     
    3232  <p>
    3333  If the implementation supports extra information, ie. the call to
    34   {@link AuthenticationManager#supportsExtraInformation()}
     34  {@link Authenticator#supportsExtraInformation()}
    3535  returns TRUE, the other fields may also contain information.
    3636 
     
    3838  @version 2.0
    3939  @base.modified $Date$
     40  @deprecated In 3.3, use {@link AuthenticatedUser} instead
    4041*/
     42@Deprecated
    4143public class AuthenticationInformation
    4244{
    4345  /**
    44     TRUE if the contructor with extra information was used, FALSE if the minial constructor was used.
     46    TRUE if the extra information has been provided, FALSE if not.
    4547    @since 3.3
    4648  */
     
    106108  public AuthenticationInformation(String login, String id)
    107109  {
    108     this(login, id, null, null, null, null, null, null, null, null, false);
     110    this(login, id, null, null, null, null, null, null, null, null);
    109111  }
    110112
     
    138140  )
    139141  {
    140     this(login, id, name, organisation, address, phone, fax, email, url, description, true);
    141   }
    142  
    143   private AuthenticationInformation
    144   (
    145     String login,
    146     String id,
    147     String name,
    148     String organisation,
    149     String address,
    150     String phone,
    151     String fax,
    152     String email,
    153     String url,
    154     String description,
    155     boolean hasExtraInfo
    156   )
    157   {
    158142    if (id == null) throw new NullPointerException("id");
    159143    if (login == null) throw new NullPointerException("login");
     
    168152    this.url = url;
    169153    this.description = description;
    170     this.hasExtraInfo = hasExtraInfo;
     154    this.hasExtraInfo = !allNull(name, organisation, address, phone, fax, email, url, description);
    171155  }
    172156
     157 
     158  private static boolean allNull(Object... objects)
     159  {
     160    for (Object o : objects)
     161    {
     162      if (o != null) return false;
     163    }
     164    return true;
     165  }
    173166}
  • trunk/src/core/net/sf/basedb/core/authentication/AuthenticationManager.java

    r6423 r6425  
    6060    @throws A {@link AuthenticationException} if the user was not authenticated
    6161  */
    62   public AuthenticationInformation authenticate();
     62  public AuthenticatedUser authenticate();
    6363 
    64   /**
    65     Should return TRUE or FALSE depending on if the authentication
    66     server returns additional information about the user.
    67       @return TRUE if additional information is returned, FALSE otherwise.
    68     @see AuthenticationInformation
    69   */
    70   public boolean supportsExtraInformation();
    7164 
    7265}
  • trunk/src/core/net/sf/basedb/core/authentication/OldAuthenticationWrapperFactory.java

    r6424 r6425  
    4646 
    4747  private Authenticator auth;
     48  private AuthenticationMethod authMethod;
    4849 
    4950  public OldAuthenticationWrapperFactory()
     
    5354    {
    5455      auth = getAuthenticator(driver);
     56      authMethod = AuthenticationMethod.getInstance(driver);
    5557    }
    5658  }
     
    6668  {
    6769    AuthenticationContext authContext = (AuthenticationContext)context.getClientContext();
    68     return new AuthenticationManager[] { new OldAuthenticationManager(auth, authContext.getLoginRequest()) };
     70    LoginRequest request = authContext.getLoginRequest();
     71    AuthenticationManager authManager = new OldAuthenticationManager(request);
     72
     73    return new AuthenticationManager[] { authManager };
    6974  }
    7075 
     
    8994  }
    9095 
    91   static class OldAuthenticationManager
     96  class OldAuthenticationManager
    9297    implements AuthenticationManager
    9398  {
    94     private final Authenticator auth;
    9599    private final LoginRequest request;
    96100
    97     OldAuthenticationManager(Authenticator auth, LoginRequest request)
     101    OldAuthenticationManager(LoginRequest request)
    98102    {
    99       this.auth = auth;
    100103      this.request = request;
    101104    }
    102105
    103106    @Override
    104     public AuthenticationInformation authenticate()
     107    public AuthenticatedUser authenticate()
    105108    {
    106       return auth.authenticate(request.getLogin(), request.getPassword());
     109      AuthenticationInformation info = auth.authenticate(request.getLogin(), request.getPassword());
     110     
     111      AuthenticatedUser authUser = new AuthenticatedUser(authMethod, info.login, info.id);
     112      if (auth.supportsExtraInformation() && info.hasExtraInfo)
     113      {
     114        ExtraUserInformation extra = new ExtraUserInformation();
     115        extra.setAddress(info.address);
     116        extra.setDescription(info.description);
     117        extra.setEmail(info.email);
     118        extra.setFax(info.fax);
     119        extra.setName(info.name);
     120        extra.setOrganisation(info.organisation);
     121        extra.setPhone(info.phone);
     122        extra.setUrl(info.url);
     123      }
     124      return authUser;
    107125    }
    108126
    109     @Override
    110     public boolean supportsExtraInformation()
    111     {
    112       return auth.supportsExtraInformation();
    113     }
    114    
    115127  }
    116128 
Note: See TracChangeset for help on using the changeset viewer.