Author: ajaquith
Date: Mon Mar 31 20:42:00 2008
New Revision: 643254

URL: http://svn.apache.org/viewvc?rev=643254&view=rev
Log:
Re-factored the authentication subsystem to remove the need for JAAS 
configuration files. WEB-INF/jspwiki.jaas goes away, as does the need for 
PolicyLoader. Also, responsibilities for web authentication move to 
WikiServletFilter. Authentication is now configured via jspwiki.properties -- 
see that file for details. WikiSession API change: getLoginContext() vanishes.

Modified:
    incubator/jspwiki/trunk/src/com/ecyrd/jspwiki/WikiContext.java
    incubator/jspwiki/trunk/src/com/ecyrd/jspwiki/WikiSession.java

Modified: incubator/jspwiki/trunk/src/com/ecyrd/jspwiki/WikiContext.java
URL: 
http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/com/ecyrd/jspwiki/WikiContext.java?rev=643254&r1=643253&r2=643254&view=diff
==============================================================================
--- incubator/jspwiki/trunk/src/com/ecyrd/jspwiki/WikiContext.java (original)
+++ incubator/jspwiki/trunk/src/com/ecyrd/jspwiki/WikiContext.java Mon Mar 31 
20:42:00 2008
@@ -194,15 +194,6 @@
      * request, and determine if a WikiSession object is present. If not, a new
      * one is created.
      * </p>
-     * <p>
-     * After the WikiSession object is obtained, the current authentication
-     * status is checked. If not authenticated, or if the login status reported
-     * by the container has changed, the constructor attempts to log in the 
user
-     * with
-     * [EMAIL PROTECTED] 
com.ecyrd.jspwiki.auth.AuthenticationManager#login(HttpServletRequest)}.
-     * If an login process throws an exception, this method logs the error but
-     * does not re-throw it.
-     * </p>
      * @param engine The WikiEngine that is handling the request
      * @param request The HttpServletRequest that should be associated with 
this
      *            context. This parameter may be <code>null</code>.
@@ -250,35 +241,12 @@
             m_command = command.targetedCommand( m_page );
         }
 
-        // Log in the user if new session or the container status changed
-        boolean doLogin = (request != null) && m_session.isNew();
-
         // Debugging...
         if( log.isDebugEnabled() )
         {
             HttpSession session = ( request == null ) ? null : 
request.getSession( false );
             String sid = ( session == null ) ? "(null)" : session.getId();
             log.debug( "Creating WikiContext for session ID=" + sid + "; 
target=" + getName() );
-            log.debug( "Do we need to log the user in? " + doLogin );
-        }
-
-        if( doLogin || m_session.isContainerStatusChanged( request ) )
-        {
-            try
-            {
-                engine.getAuthenticationManager().login( request );
-            }
-            catch ( WikiSecurityException e )
-            {
-                // Login failed because config was screwy
-                log.error( "Could not log in user: " + e.getMessage() );
-            }
-        }
-
-        // Mark the session as "not new"
-        if( m_session.isNew() )
-        {
-            m_session.setNew( false );
         }
 
         // Figure out what template to use

Modified: incubator/jspwiki/trunk/src/com/ecyrd/jspwiki/WikiSession.java
URL: 
http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/com/ecyrd/jspwiki/WikiSession.java?rev=643254&r1=643253&r2=643254&view=diff
==============================================================================
--- incubator/jspwiki/trunk/src/com/ecyrd/jspwiki/WikiSession.java (original)
+++ incubator/jspwiki/trunk/src/com/ecyrd/jspwiki/WikiSession.java Mon Mar 31 
20:42:00 2008
@@ -26,9 +26,6 @@
 import java.util.*;
 
 import javax.security.auth.Subject;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.login.LoginContext;
-import javax.security.auth.login.LoginException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpSession;
 
@@ -38,8 +35,6 @@
 import com.ecyrd.jspwiki.auth.authorize.Group;
 import com.ecyrd.jspwiki.auth.authorize.GroupManager;
 import com.ecyrd.jspwiki.auth.authorize.Role;
-import com.ecyrd.jspwiki.auth.login.CookieAssertionLoginModule;
-import com.ecyrd.jspwiki.auth.login.PrincipalWrapper;
 import com.ecyrd.jspwiki.auth.user.UserDatabase;
 import com.ecyrd.jspwiki.auth.user.UserProfile;
 import com.ecyrd.jspwiki.event.WikiEvent;
@@ -117,17 +112,9 @@
 
     private final Map           m_messages            = new HashMap();
 
-    private String              m_cachedCookieIdentity= null;
-
-    private String              m_cachedRemoteUser    = null;
-
-    private Principal           m_cachedUserPrincipal = null;
-
     /** The WikiEngine that created this session. */
     private WikiEngine          m_engine              = null;
 
-    private boolean             m_isNew               = true;
-
     private String              m_status              = ANONYMOUS;
 
     private Principal           m_userPrincipal       = WikiPrincipal.GUEST;
@@ -157,25 +144,6 @@
     }
 
     /**
-     * Returns <code>true</code> if the wiki session is newly initialized.
-     *
-     * @return True, if this is a new session.
-     */
-    protected final boolean isNew()
-    {
-        return m_isNew;
-    }
-
-    /**
-     * Sets the status of this wiki session.
-     * @param isNew whether this session should be considered "new".
-     */
-    protected final void setNew( boolean isNew )
-    {
-        m_isNew = isNew;
-    }
-
-    /**
      * Private constructor to prevent WikiSession from being instantiated
      * directly.
      */
@@ -247,20 +215,6 @@
     }
 
     /**
-     * Creates and returns a new login context for this wiki session.
-     * This method is called by
-     * [EMAIL PROTECTED] com.ecyrd.jspwiki.auth.AuthenticationManager}.
-     * @param application the name of the application
-     * @param handler the callback handler
-     * @return A new login context
-     * @throws LoginException If the login context cannot be created
-     */
-    public final LoginContext getLoginContext( String application, 
CallbackHandler handler ) throws LoginException
-    {
-        return new LoginContext( application, m_subject, handler );
-    }
-
-    /**
      * <p> Returns the Principal used to log in to an authenticated session. 
The
      * login principal is determined by examining the Subject's Principal set
      * for PrincipalWrappers or WikiPrincipals with type designator
@@ -274,10 +228,6 @@
      */
     public final Principal getLoginPrincipal()
     {
-        if ( m_loginPrincipal instanceof PrincipalWrapper )
-        {
-            return ((PrincipalWrapper)m_loginPrincipal).getPrincipal();
-        }
         return m_loginPrincipal;
     }
 
@@ -296,10 +246,6 @@
      */
     public final Principal getUserPrincipal()
     {
-        if ( m_loginPrincipal instanceof PrincipalWrapper )
-        {
-            return ((PrincipalWrapper)m_userPrincipal).getPrincipal();
-        }
         return m_userPrincipal;
     }
 
@@ -530,10 +476,35 @@
                     }
                     case WikiSecurityEvent.LOGIN_INITIATED:
                     {
+                        // Do nothing
+                    }
+                    case WikiSecurityEvent.PRINCIPAL_ADD:
+                    {
+                        WikiSession target = (WikiSession)e.getTarget();
+                        if ( this.equals( target ) & m_status == AUTHENTICATED 
)
+                        {
+                            Set principals = m_subject.getPrincipals();
+                            principals.add(e.getPrincipal());
+                        }
+                        break;
+                    }
+                    case WikiSecurityEvent.LOGIN_ANONYMOUS:
+                    {
                         WikiSession target = (WikiSession)e.getTarget();
                         if ( this.equals( target ) )
                         {
-                            updatePrincipals();
+                            m_status = ANONYMOUS;
+                            
+                            // Set the login/user principals and login status
+                            Set principals = m_subject.getPrincipals();
+                            m_loginPrincipal = (Principal)e.getPrincipal();
+                            m_userPrincipal = m_loginPrincipal;
+                            
+                            // Add the login principal to the Subject, and set 
the built-in roles
+                            principals.clear();
+                            principals.add(m_loginPrincipal);
+                            principals.add(Role.ALL);
+                            principals.add(Role.ANONYMOUS);
                         }
                         break;
                     }
@@ -543,6 +514,17 @@
                         if ( this.equals( target ) )
                         {
                             m_status = ASSERTED;
+                            
+                            // Set the login/user principals and login status
+                            Set principals = m_subject.getPrincipals();
+                            m_loginPrincipal = (Principal)e.getPrincipal();
+                            m_userPrincipal = m_loginPrincipal;
+                            
+                            // Add the login principal to the Subject, and set 
the built-in roles
+                            principals.clear();
+                            principals.add(m_loginPrincipal);
+                            principals.add(Role.ALL);
+                            principals.add(Role.ASSERTED);
                         }
                         break;
                     }
@@ -552,9 +534,21 @@
                         if ( this.equals( target ) )
                         {
                             m_status = AUTHENTICATED;
+                            
+                            // Set the login/user principals and login status
+                            Set principals = m_subject.getPrincipals();
+                            m_loginPrincipal = (Principal)e.getPrincipal();
+                            m_userPrincipal = m_loginPrincipal;
+                            
+                            // Add the login principal to the Subject, and set 
the built-in roles
+                            principals.clear();
+                            principals.add(m_loginPrincipal);
+                            principals.add(Role.ALL);
+                            principals.add(Role.AUTHENTICATED);
+                            
+                            // Add the user and group principals
                             injectUserProfilePrincipals();  // Add principals 
for the user profile
-                            injectRolePrincipals();  // Inject role and group 
principals
-                            updatePrincipals();
+                            injectGroupPrincipals();  // Inject group 
principals
                         }
                         break;
                     }
@@ -564,7 +558,7 @@
                         if ( this.equals( source ) )
                         {
                             injectUserProfilePrincipals();  // Add principals 
for the user profile
-                            updatePrincipals();
+                            injectGroupPrincipals();  // Inject group 
principals
                         }
                         break;
                     }
@@ -572,7 +566,7 @@
                     {
                         // Refresh user principals based on new user profile
                         WikiSession source = (WikiSession)e.getSource();
-                        if ( this.equals( source ) )
+                        if ( this.equals( source ) && m_status == 
AUTHENTICATED )
                         {
                             // To prepare for refresh, set the new full name 
as the primary principal
                             UserProfile[] profiles = 
(UserProfile[])e.getTarget();
@@ -581,11 +575,19 @@
                             {
                                 throw new IllegalStateException( "User profile 
FullName cannot be null." );
                             }
-                            m_userPrincipal = new WikiPrincipal( 
newProfile.getFullname() );
-
-                            // Refresh principals for the user profile
-                            injectUserProfilePrincipals();
-                            updatePrincipals();
+                            
+                            Set principals = m_subject.getPrincipals();
+                            m_loginPrincipal = new WikiPrincipal( 
newProfile.getLoginName() );
+                            
+                            // Add the login principal to the Subject, and set 
the built-in roles
+                            principals.clear();
+                            principals.add( m_loginPrincipal );
+                            principals.add( Role.ALL );
+                            principals.add( Role.AUTHENTICATED );
+                            
+                            // Add the user and group principals
+                            injectUserProfilePrincipals();  // Add principals 
for the user profile
+                            injectGroupPrincipals();  // Inject group 
principals
                         }
                         break;
                     }
@@ -610,83 +612,26 @@
         m_subject.getPrincipals().add( WikiPrincipal.GUEST );
         m_subject.getPrincipals().add( Role.ANONYMOUS );
         m_subject.getPrincipals().add( Role.ALL );
-        m_cachedCookieIdentity = null;
-        m_cachedRemoteUser = null;
-        m_cachedUserPrincipal = null;
     }
 
     /**
-     * Returns whether the HTTP servlet container's authentication status has
-     * changed. Used to detect whether the container has logged in a user since
-     * the last call to this function. This method is stateful. After calling
-     * this function, the cached values are set to those in the current 
request.
-     * If the servlet request is <code>null</code>, this method always returns
-     * <code>false</code>. Note that once a user authenticates, the container
-     * status for the session will <em>never</em> change again, unless the
-     * session is invalidated by timeout or logout.
-     * @param request the servlet request
-     * @return <code>true</code> if the status has changed, <code>false</code>
-     * otherwise
-     */
-    protected final boolean isContainerStatusChanged( HttpServletRequest 
request )
-    {
-        if ( request == null || m_status.equals( AUTHENTICATED ) )
-        {
-            return false;
-        }
-
-        String remoteUser = request.getRemoteUser();
-        Principal userPrincipal = request.getUserPrincipal();
-        String cookieIdentity = CookieAssertionLoginModule.getUserCookie( 
request );
-        boolean changed = false;
-
-        // If request contains non-null remote user, update cached value if 
changed
-        if ( remoteUser != null && !remoteUser.equals( m_cachedRemoteUser) )
-        {
-            m_cachedRemoteUser = remoteUser;
-            log.info( "Remote user changed to " + remoteUser );
-            changed = true;
-        }
-
-        // If request contains non-null user principal, updated cached value 
if changed
-        if ( userPrincipal != null && !userPrincipal.equals( 
m_cachedUserPrincipal ) )
-        {
-            m_cachedUserPrincipal = userPrincipal;
-            log.info( "User principal changed to " + userPrincipal.getName() );
-            changed = true;
-        }
-
-        // If cookie identity changed (to a different value or back to null), 
update cache
-        if ( ( cookieIdentity != null && !cookieIdentity.equals( 
m_cachedCookieIdentity ) )
-               || ( cookieIdentity == null && m_cachedCookieIdentity != null ) 
)
-        {
-            m_cachedCookieIdentity = cookieIdentity;
-            log.info( "Cookie changed to " + cookieIdentity );
-            changed = true;
-        }
-        return changed;
-    }
-
-    /**
-     * Injects GroupPrincipal and Role objects into the user's Principal set
-     * based on the groups and roles the user belongs to.
-     * For Roles, the algorithm first calls the
-     * [EMAIL PROTECTED] Authorizer#getRoles()} to obtain the array of
-     * Principals the authorizer knows about. Then, the method
-     * [EMAIL PROTECTED] Authorizer#isUserInRole(WikiSession, Principal)} is
-     * called for each Principal. If the user possesses the role,
-     * an equivalent role Principal is injected into the user's
-     * principal set.
-     * Reloads user Principals into the suppplied WikiSession's Subject.
-     * Existing Role principals are preserved; all other Principal
-     * types are flushed and replaced by those returned by
-     * [EMAIL PROTECTED] 
com.ecyrd.jspwiki.auth.user.UserDatabase#getPrincipals(String)}.
-     * This method should generally be called after a user's [EMAIL PROTECTED] 
com.ecyrd.jspwiki.auth.user.UserProfile}
-     * is saved. If the wiki session is null, or there is no matching user 
profile, the
-     * method returns silently.
-     */
-    protected final void injectRolePrincipals()
-    {
+     * Injects GroupPrincipal objects into the user's Principal set based on 
the
+     * groups the user belongs to. For Groups, the algorithm first calls the
+     * [EMAIL PROTECTED] GroupManager#getRoles()} to obtain the array of 
GroupPrincipals
+     * the authorizer knows about. Then, the method
+     * [EMAIL PROTECTED] GroupManager#isUserInRole(WikiSession, Principal)} is 
called for
+     * each Principal. If the user is a member of the group, an equivalent
+     * GroupPrincipal is injected into the user's principal set. Existing
+     * GroupPrincipals are flushed and replaced. This method should generally 
be
+     * called after a user's [EMAIL PROTECTED] 
com.ecyrd.jspwiki.auth.user.UserProfile} is
+     * saved. If the wiki session is null, or there is no matching user 
profile,
+     * the method returns silently.
+     */
+    protected final void injectGroupPrincipals()
+    {
+        // Flush the existing GroupPrincipals
+        
m_subject.getPrincipals().removeAll(m_subject.getPrincipals(GroupPrincipal.class));
+        
         // Get the GroupManager and test for each Group
         GroupManager manager = m_engine.getGroupManager();
         Principal[] groups = manager.getRoles();
@@ -697,29 +642,6 @@
                 m_subject.getPrincipals().add( groups[i] );
             }
         }
-
-        // Get the authorizer's known roles, then test for each
-        try
-        {
-            Authorizer authorizer = 
m_engine.getAuthorizationManager().getAuthorizer();
-            Principal[] roles = authorizer.getRoles();
-            for ( int i = 0; i < roles.length; i++ )
-            {
-                Principal role = roles[i];
-                if ( authorizer.isUserInRole( this, role ) )
-                {
-                    String roleName = role.getName();
-                    if ( !Role.isReservedName( roleName ) )
-                    {
-                        m_subject.getPrincipals().add( new Role( roleName ) );
-                    }
-                }
-            }
-        }
-        catch ( WikiException e )
-        {
-            log.error( "Could not refresh role principals: " + e.getMessage() 
);
-        }
     }
 
     /**
@@ -731,18 +653,8 @@
      */
     protected final void injectUserProfilePrincipals()
     {
-        // Copy all Role and GroupPrincipal principals into a temporary cache
-        Set oldPrincipals = m_subject.getPrincipals();
-        Set newPrincipals = new HashSet();
-        for (Iterator it = oldPrincipals.iterator(); it.hasNext();)
-        {
-            Principal principal = (Principal)it.next();
-            if ( AuthenticationManager.isRolePrincipal( principal ) )
-            {
-                newPrincipals.add( principal );
-            }
-        }
-        String searchId = getUserPrincipal().getName();
+        // Search for the user profile
+        String searchId = m_loginPrincipal.getName();
         if ( searchId == null )
         {
             // Oh dear, this wasn't an authenticated user after all
@@ -762,105 +674,27 @@
             Principal[] principals = database.getPrincipals( 
profile.getLoginName() );
             for (int i = 0; i < principals.length; i++)
             {
+                // Add the Principal to the Subject
                 Principal principal = principals[i];
-                newPrincipals.add( principal );
-            }
-
-            // Replace the Subject's old Principals with the new ones
-            oldPrincipals.clear();
-            oldPrincipals.addAll( newPrincipals );
-        }
-        catch ( NoSuchPrincipalException e )
-        {
-            // We will get here if the user has a principal but not a profile
-            // For example, it's a container-managed user who hasn't set up a 
profile yet
-            log.warn("User profile '" + searchId + "' not found. This is 
normal for container-auth users who haven't set up a profile yet.");
-        }
-    }
-
-    /**
-     * Updates the internally cached principals returned by [EMAIL PROTECTED] 
#getUserPrincipal()} and
-     * [EMAIL PROTECTED] #getLoginPrincipal()}. This method is called when the 
WikiSession receives
-     * the [EMAIL PROTECTED] 
com.ecyrd.jspwiki.event.WikiSecurityEvent#LOGIN_INITIATED} message.
-     */
-    protected final void updatePrincipals()
-    {
-        Set principals = m_subject.getPrincipals();
-        m_loginPrincipal = null;
-        m_userPrincipal = null;
-        Principal wikinamePrincipal = null;
-        Principal fullnamePrincipal = null;
-        Principal otherPrincipal = null;
-
-        for( Iterator it = principals.iterator(); it.hasNext(); )
-        {
-            Principal currentPrincipal = (Principal) it.next();
-            if ( !( currentPrincipal instanceof Role || currentPrincipal 
instanceof GroupPrincipal ) )
-            {
-                // For login principal, take the first PrincipalWrapper or 
WikiPrincipal of type LOGIN_NAME
-                // For user principal take the  first WikiPrincipal of type 
WIKI_NAME
-                if ( currentPrincipal instanceof PrincipalWrapper )
+                m_subject.getPrincipals().add( principal );
+                
+                // Set the user principal if needed; we prefer FullName, but 
the WikiName will also work
+                boolean isFullNamePrincipal = (principal instanceof 
WikiPrincipal && ((WikiPrincipal)principal).getType() == 
WikiPrincipal.FULL_NAME);
+                if (isFullNamePrincipal)
                 {
-                    m_loginPrincipal = currentPrincipal;
+                   m_userPrincipal = principal; 
                 }
-                else if ( currentPrincipal instanceof WikiPrincipal )
+                else if (!(m_userPrincipal instanceof WikiPrincipal))
                 {
-                    WikiPrincipal wp = (WikiPrincipal) currentPrincipal;
-                    if ( wp.getType().equals( WikiPrincipal.LOGIN_NAME ) )
-                    {
-                        m_loginPrincipal = wp;
-                    }
-                    else if ( wp.getType().equals( WikiPrincipal.WIKI_NAME ) )
-                    {
-                        wikinamePrincipal = currentPrincipal;
-                        m_userPrincipal = wp;
-                    }
-                    else if ( wp.getType().equals( WikiPrincipal.FULL_NAME ) )
-                    {
-                        fullnamePrincipal = currentPrincipal;
-                    }
-                    else
-                    {
-                        otherPrincipal = currentPrincipal;
-                    }
-                }
-                else if ( otherPrincipal == null )
-                {
-                    otherPrincipal = currentPrincipal;
+                    m_userPrincipal = principal; 
                 }
             }
         }
-        if ( otherPrincipal == null )
-        {
-            otherPrincipal = WikiPrincipal.GUEST;
-        }
-
-        // If no login principal, use wiki name, full name or other principal 
(in that order)
-        if ( m_loginPrincipal == null )
-        {
-            m_loginPrincipal = wikinamePrincipal;
-            if ( m_loginPrincipal == null )
-            {
-                m_loginPrincipal = fullnamePrincipal;
-                if ( m_loginPrincipal == null )
-                {
-                    m_loginPrincipal = otherPrincipal;
-                }
-            }
-        }
-
-        // If no user principal, use wiki name, full name or login principal 
(in that order)
-        if ( m_userPrincipal == null )
+        catch ( NoSuchPrincipalException e )
         {
-            m_userPrincipal = wikinamePrincipal;
-            if ( m_userPrincipal == null )
-            {
-                m_userPrincipal = fullnamePrincipal;
-                if ( m_userPrincipal == null )
-                {
-                    m_userPrincipal = m_loginPrincipal;
-                }
-            }
+            // We will get here if the user has a principal but not a profile
+            // For example, it's a container-managed user who hasn't set up a 
profile yet
+            log.warn("User profile '" + searchId + "' not found. This is 
normal for container-auth users who haven't set up a profile yet.");
         }
     }
 


Reply via email to