You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2008/01/10 22:09:28 UTC

svn commit: r610930 - in /tomcat/tc6.0.x/trunk: ./ java/org/apache/catalina/ha/session/ test/org/apache/catalina/ha/ test/org/apache/catalina/ha/session/ webapps/docs/

Author: markt
Date: Thu Jan 10 13:09:27 2008
New Revision: 610930

URL: http://svn.apache.org/viewvc?rev=610930&view=rev
Log:
Fix bug 43840. Include user principal if possible when serializing de-serializing sessions.

Added:
    tomcat/tc6.0.x/trunk/test/org/apache/catalina/ha/
    tomcat/tc6.0.x/trunk/test/org/apache/catalina/ha/session/
    tomcat/tc6.0.x/trunk/test/org/apache/catalina/ha/session/TestPrincipal.java   (with props)
    tomcat/tc6.0.x/trunk/test/org/apache/catalina/ha/session/TestSerializablePrincipal.java   (with props)
Modified:
    tomcat/tc6.0.x/trunk/STATUS.txt
    tomcat/tc6.0.x/trunk/java/org/apache/catalina/ha/session/LocalStrings.properties
    tomcat/tc6.0.x/trunk/java/org/apache/catalina/ha/session/SerializablePrincipal.java
    tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml

Modified: tomcat/tc6.0.x/trunk/STATUS.txt
URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/STATUS.txt?rev=610930&r1=610929&r2=610930&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/STATUS.txt (original)
+++ tomcat/tc6.0.x/trunk/STATUS.txt Thu Jan 10 13:09:27 2008
@@ -31,12 +31,6 @@
   +1: jfclere
   -1: fhanik - Can we add the 'package' directive to make the package match the dir structure
 
-* Fix http://issues.apache.org/bugzilla/show_bug.cgi?id=43840
-  Include user principal if possible when serializing / de-serializing
-  http://people.apache.org/~markt/dev/bug43840.txt
-  +1: markt, fhanik, pero
-  -1:
-
 * Improve Jasper docs. Note rather than remove unused option, it will be
   deprecated in 6.0.x.
   http://svn.apache.org/viewvc?rev=607860&view=rev

Modified: tomcat/tc6.0.x/trunk/java/org/apache/catalina/ha/session/LocalStrings.properties
URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/catalina/ha/session/LocalStrings.properties?rev=610930&r1=610929&r2=610930&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/catalina/ha/session/LocalStrings.properties (original)
+++ tomcat/tc6.0.x/trunk/java/org/apache/catalina/ha/session/LocalStrings.properties Thu Jan 10 13:09:27 2008
@@ -109,3 +109,4 @@
 standardSession.setAttribute.ise=setAttribute: Session already invalidated
 standardSession.setAttribute.namenull=setAttribute: name parameter cannot be null
 standardSession.sessionCreated=Created Session id = {0}
+serializablePrincipal.readPrincipal.cnfe=readPrincipal: Failed to recreate user Principal
\ No newline at end of file

Modified: tomcat/tc6.0.x/trunk/java/org/apache/catalina/ha/session/SerializablePrincipal.java
URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/catalina/ha/session/SerializablePrincipal.java?rev=610930&r1=610929&r2=610930&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/catalina/ha/session/SerializablePrincipal.java (original)
+++ tomcat/tc6.0.x/trunk/java/org/apache/catalina/ha/session/SerializablePrincipal.java Thu Jan 10 13:09:27 2008
@@ -19,31 +19,47 @@
 package org.apache.catalina.ha.session;
 
 
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.io.Serializable;
+
+import java.security.Principal;
+
 import java.util.Arrays;
 import java.util.List;
+
 import org.apache.catalina.Realm;
+import org.apache.catalina.realm.GenericPrincipal;
+import org.apache.catalina.util.StringManager;
 
 
 /**
  * Generic implementation of <strong>java.security.Principal</strong> that
  * is available for use by <code>Realm</code> implementations.
- * The GenericPrincipal does NOT implement serializable and I didn't want to change that implementation
- * hence I implemented this one instead.
+ * The GenericPrincipal does NOT implement serializable and I didn't want to
+ * change that implementation hence I implemented this one instead.
  * @author Filip Hanik
  * @version $Revision$ $Date$
  */
-import org.apache.catalina.realm.GenericPrincipal;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
 public class SerializablePrincipal  implements java.io.Serializable {
 
+    protected static org.apache.juli.logging.Log log =
+        org.apache.juli.logging.LogFactory.getLog(SerializablePrincipal.class);
+    
+    /**
+     * The string manager for this package.
+     */
+    protected static StringManager sm =
+        StringManager.getManager(Constants.Package);
 
     // ----------------------------------------------------------- Constructors
 
-    public SerializablePrincipal()
-    {
+    public SerializablePrincipal() {
         super();
     }
+    
+    
     /**
      * Construct a new Principal, associated with the specified Realm, for the
      * specified username and password.
@@ -70,7 +86,24 @@
      * @param roles List of roles (must be Strings) possessed by this user
      */
     public SerializablePrincipal(Realm realm, String name, String password,
-                            List roles) {
+                            List<String> roles) {
+        this(realm, name, password, roles, null);
+    }
+
+    
+    /**
+     * Construct a new Principal, associated with the specified Realm, for the
+     * specified username and password, with the specified role names
+     * (as Strings).
+     *
+     * @param realm The Realm that owns this principal
+     * @param name The username of the user represented by this Principal
+     * @param password Credentials used to authenticate this user
+     * @param roles List of roles (must be Strings) possessed by this user
+     * @param userPrincipal The user principal to be exposed to applications
+     */
+    public SerializablePrincipal(Realm realm, String name, String password,
+                            List<String> roles, Principal userPrincipal) {
 
         super();
         this.realm = realm;
@@ -78,11 +111,13 @@
         this.password = password;
         if (roles != null) {
             this.roles = new String[roles.size()];
-            this.roles = (String[]) roles.toArray(this.roles);
+            this.roles = roles.toArray(this.roles);
             if (this.roles.length > 0)
                 Arrays.sort(this.roles);
         }
-
+        if (userPrincipal instanceof Serializable) {
+            this.userPrincipal = userPrincipal;
+        }
     }
 
 
@@ -136,6 +171,11 @@
     }
 
 
+    /**
+     * The user principal, if present.
+     */
+    protected Principal userPrincipal = null;
+    
     // --------------------------------------------------------- Public Methods
 
 
@@ -160,15 +200,19 @@
         return new SerializablePrincipal(principal.getRealm(),
                                          principal.getName(),
                                          principal.getPassword(),
-                                         principal.getRoles()!=null?Arrays.asList(principal.getRoles()):null);
+                                         principal.getRoles()!=null?Arrays.asList(principal.getRoles()):null,
+                                         principal.getUserPrincipal()!=principal?principal.getUserPrincipal():null);
     }
 
     public GenericPrincipal getPrincipal( Realm realm )
     {
-        return new GenericPrincipal(realm,name,password,getRoles()!=null?Arrays.asList(getRoles()):null);
+        return new GenericPrincipal(realm, name, password,
+                getRoles()!=null?Arrays.asList(getRoles()):null,
+                userPrincipal);
     }
     
-    public static GenericPrincipal readPrincipal(ObjectInput in, Realm realm) throws java.io.IOException{
+    public static GenericPrincipal readPrincipal(ObjectInput in, Realm realm)
+            throws IOException, ClassNotFoundException {
         String name = in.readUTF();
         boolean hasPwd = in.readBoolean();
         String pwd = null;
@@ -176,10 +220,23 @@
         int size = in.readInt();
         String[] roles = new String[size];
         for ( int i=0; i<size; i++ ) roles[i] = in.readUTF();
-        return new GenericPrincipal(realm,name,pwd,Arrays.asList(roles));
+        Principal userPrincipal = null;
+        boolean hasUserPrincipal = in.readBoolean();
+        if (hasUserPrincipal) {
+            try {
+                userPrincipal = (Principal) in.readObject();
+            } catch (ClassNotFoundException e) {
+                log.error(sm.getString(
+                        "serializablePrincipal.readPrincipal.cnfe"), e);
+                throw e;
+            }
+        }
+        return new GenericPrincipal(realm,name,pwd,Arrays.asList(roles),
+                userPrincipal);
     }
     
-    public static void writePrincipal(GenericPrincipal p, ObjectOutput out) throws java.io.IOException {
+    public static void writePrincipal(GenericPrincipal p, ObjectOutput out)
+            throws IOException {
         out.writeUTF(p.getName());
         out.writeBoolean(p.getPassword()!=null);
         if ( p.getPassword()!= null ) out.writeUTF(p.getPassword());
@@ -187,6 +244,10 @@
         if ( roles == null ) roles = new String[0];
         out.writeInt(roles.length);
         for ( int i=0; i<roles.length; i++ ) out.writeUTF(roles[i]);
+        boolean hasUserPrincipal = (p != p.getUserPrincipal() &&
+                p.getUserPrincipal() instanceof Serializable);
+        out.writeBoolean(hasUserPrincipal);
+        if (hasUserPrincipal) out.writeObject(p.getUserPrincipal());
     }
 
 

Added: tomcat/tc6.0.x/trunk/test/org/apache/catalina/ha/session/TestPrincipal.java
URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/test/org/apache/catalina/ha/session/TestPrincipal.java?rev=610930&view=auto
==============================================================================
--- tomcat/tc6.0.x/trunk/test/org/apache/catalina/ha/session/TestPrincipal.java (added)
+++ tomcat/tc6.0.x/trunk/test/org/apache/catalina/ha/session/TestPrincipal.java Thu Jan 10 13:09:27 2008
@@ -0,0 +1,35 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.catalina.ha.session;
+
+import java.io.Serializable;
+import java.security.Principal;
+
+public class TestPrincipal implements Principal, Serializable {
+    
+    private String name;
+
+    public TestPrincipal(String theName) {
+        name = theName;
+    }
+    
+    public String getName() {
+        return name;
+    }
+    
+}
\ No newline at end of file

Propchange: tomcat/tc6.0.x/trunk/test/org/apache/catalina/ha/session/TestPrincipal.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tomcat/tc6.0.x/trunk/test/org/apache/catalina/ha/session/TestSerializablePrincipal.java
URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/test/org/apache/catalina/ha/session/TestSerializablePrincipal.java?rev=610930&view=auto
==============================================================================
--- tomcat/tc6.0.x/trunk/test/org/apache/catalina/ha/session/TestSerializablePrincipal.java (added)
+++ tomcat/tc6.0.x/trunk/test/org/apache/catalina/ha/session/TestSerializablePrincipal.java Thu Jan 10 13:09:27 2008
@@ -0,0 +1,108 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.catalina.ha.session;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.catalina.realm.GenericPrincipal;
+
+import junit.framework.TestCase;
+
+public class TestSerializablePrincipal extends TestCase {
+
+    /**
+     * Simple serialization / de-serialization test for bug 43840.
+     */
+    public void testWriteReadPrincipal() {
+        // Get a temporary file to use for the serialization test
+        File file = null;
+        try {
+            file = File.createTempFile("ser", null);
+            file.deleteOnExit();
+        } catch (IOException e) {
+            e.printStackTrace();
+            fail("ioe creating temporary file");
+        }
+        
+        // Create the Principal to serialize
+        List<String> roles = new ArrayList<String>();
+        roles.add("RoleA");
+        roles.add("RoleB");
+        TestPrincipal tpOriginal = new TestPrincipal("inner");
+        GenericPrincipal gpOriginal =
+            new GenericPrincipal(null, "usr", "pwd", roles, tpOriginal);
+        
+        // Do the serialization
+        try {
+            FileOutputStream fos = new FileOutputStream(file);
+            ObjectOutputStream oos = new ObjectOutputStream(fos);
+            SerializablePrincipal.writePrincipal(gpOriginal, oos);
+            oos.close();
+            fos.close();
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+            fail("fnfe creating object output stream");
+        } catch (IOException e) {
+            e.printStackTrace();
+            fail("ioe serializing principal");
+        }
+        
+        // De-serialize the Principal
+        GenericPrincipal gpNew = null;
+        try {
+            FileInputStream fis = new FileInputStream(file);
+            ObjectInputStream ois = new ObjectInputStream(fis);
+            gpNew = SerializablePrincipal.readPrincipal(ois, null);
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+            fail("fnfe reading object output stream");
+        } catch (IOException e) {
+            e.printStackTrace();
+            fail("ioe de-serializing principal");
+        } catch (ClassNotFoundException e) {
+            e.printStackTrace();
+            fail("cnfe de-serializing principal");
+        }
+        
+        // Now test how similar original and de-serialized versions are
+        assertEquals("User names different", gpOriginal.getName(),
+                gpNew.getName());
+        assertEquals("Passwords different", gpOriginal.getPassword(),
+                gpNew.getPassword());
+        assertEquals("Number of roles different", gpOriginal.getRoles().length,
+                gpNew.getRoles().length);
+        for (int i = 0; i < gpOriginal.getRoles().length; i++) {
+            assertEquals("Role name index " + i + "different",
+                    gpOriginal.getRoles()[i], gpNew.getRoles()[i]);
+        }
+        // These are the key tests for bug 43840
+        assertNotSame("Inner principal not present", gpNew,
+                gpNew.getUserPrincipal());
+        assertEquals("Inner user names are different", tpOriginal.getName(),
+                gpNew.getUserPrincipal().getName());
+    }
+
+}

Propchange: tomcat/tc6.0.x/trunk/test/org/apache/catalina/ha/session/TestSerializablePrincipal.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml
URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml?rev=610930&r1=610929&r2=610930&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml Thu Jan 10 13:09:27 2008
@@ -97,6 +97,14 @@
         a patch by Panagiotis Astithas. (markt)
       </fix>
       <fix>
+        <bug>43840</bug>: Include user principal if possible when serializing /
+        de-serializing sessions. (markt)
+      </fix>
+      <fix>
+        <bug>43868</bug>: MBean methods getInvoke and getSetter were broken.
+        (markt)
+      </fix>
+      <fix>
         <bug>43887</bug>: Make error messages much more helpful when illegal
         Servlet names are used. Based on a patch provided by Mike Baranczak.
         (markt)
@@ -108,10 +116,6 @@
         Improve the webDAV Servlet Javadocs to make clear that the WebDAV
         Servlet can not be used as the default servlet. (markt)
       </update>
-      <fix>
-        <bug>43868</bug>: MBean methods getInvoke and getSetter were broken.
-        (markt)
-      </fix>
       <fix>
         <bug>43993</bug>: mime mapping for WS-Policy. Patch by Fabian Ritzmann  (funkman)
       </fix>



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org