From db0b00aa09b2f0a6292ea1282773eaa4e92b1d29 Mon Sep 17 00:00:00 2001 From: maxcooper Date: Wed, 14 Aug 2002 13:13:23 +0000 Subject: [PATCH] all session items are now serializable implemented spec-compliant url-pattern ordering --- .../securityfilter/filter/MatchableURLPattern.java | 121 +++++++++++++++++--- .../org/securityfilter/filter/SavedRequest.java | 13 ++- .../org/securityfilter/filter/SecurityFilter.java | 13 ++- .../org/securityfilter/realm/SimplePrincipal.java | 126 +++++++++++++++++++++ .../realm/SimpleSecurityRealmBase.java | 15 +-- 5 files changed, 256 insertions(+), 32 deletions(-) create mode 100644 src/share/org/securityfilter/realm/SimplePrincipal.java diff --git a/src/share/org/securityfilter/filter/MatchableURLPattern.java b/src/share/org/securityfilter/filter/MatchableURLPattern.java index 0f01268..a577ad3 100644 --- a/src/share/org/securityfilter/filter/MatchableURLPattern.java +++ b/src/share/org/securityfilter/filter/MatchableURLPattern.java @@ -1,7 +1,7 @@ /* - * $Header: /cvsroot/securityfilter/securityfilter/src/share/org/securityfilter/filter/Attic/MatchableURLPattern.java,v 1.3 2002/08/12 01:34:28 maxcooper Exp $ - * $Revision: 1.3 $ - * $Date: 2002/08/12 01:34:28 $ + * $Header: /cvsroot/securityfilter/securityfilter/src/share/org/securityfilter/filter/Attic/MatchableURLPattern.java,v 1.4 2002/08/14 13:13:23 maxcooper Exp $ + * $Revision: 1.4 $ + * $Date: 2002/08/14 13:13:23 $ * * ==================================================================== * The SecurityFilter Software License, Version 1.1 @@ -69,7 +69,7 @@ import java.util.Collection; * by the order field). * * @author Max Cooper (max@maxcooper.com) - * @version $Revision: 1.3 $ $Date: 2002/08/12 01:34:28 $ + * @version $Revision: 1.4 $ $Date: 2002/08/14 13:13:23 $ */ public class MatchableURLPattern implements Comparable { private String pattern; @@ -77,6 +77,8 @@ public class MatchableURLPattern implements Comparable { private SecurityConstraint constraint; private WebResourceCollection resourceCollection; private int order; + private int patternType; + private int pathLength; /** * Construct a new MatchableURLPattern object. @@ -100,7 +102,7 @@ public class MatchableURLPattern implements Comparable { this.constraint = constraint; this.resourceCollection = resourceCollection; this.order = order; - this.patternRE = new RE(compiler.compile(getConvertedPattern())); + init(compiler); } /** @@ -121,6 +123,28 @@ public class MatchableURLPattern implements Comparable { } /** + * Pattern type for patterns that do not meet the PATH or EXTENSION pattern type specifications. + */ + public static final int EXACT = 1; + /** + * Pattern type for PATH mappings. Starts with '/' and ends with '/*'. + */ + public static final int PATH = 2; + /** + * Pattern type for PATH mappings + */ + public static final int EXTENSION = 3; + + /** + * Get the pattern type. The pattern type will be determined on the first call to this method. + * + * @return EXACT, PATH, or EXTENSION + */ + public int getPatternType() { + return patternType; + } + + /** * Get the url pattern to match. */ public String getPattern() { @@ -169,24 +193,93 @@ public class MatchableURLPattern implements Comparable { } /** - * Compares this MatchableURLPattern to another to support sorting. - * Ordering is currently implemented according to the order field value, which can exhibit behavior inconsistent - * with equals() if non-equivalent instances have the same order value. + * Compares this MatchableURLPattern to another to support sorting.

* - * TO-DO: Update to support servlet spec compliant ordering. + * The sort order is dictated by the servlet spec. EXACT patterns are first, followed by PATH patterns, + * followed by EXTENTION patterns. Ordering among PATH patterns is determined by path length, with the + * longer path coming first. If the path lengths are the same, or both are EXACT or EXTENSION patterns, + * ordering is determined by the order in which the pattern appeared in the config file. * - * @param o object to compare to + * @param another another MatchableURLPattern to compare to + * + * @return a negative integer, zero, or a positive integer as this object is less than, equal to, or greater + * than the specified object. * * @exception ClassCastException thrown if o is not a MatchableURLPattern instance */ - public int compareTo(Object o) throws ClassCastException { - MatchableURLPattern otherPattern = (MatchableURLPattern) o; + public int compareTo(Object another) throws ClassCastException { + MatchableURLPattern otherPattern = (MatchableURLPattern) another; + // if the patterns are equivalent, ordering priority is equal if (this.equals(otherPattern)) { return 0; } else { - // TO-DO: update to reflect servlet spec pattern order - return (getOrder() - otherPattern.getOrder()); + int otherPatternType = otherPattern.getPatternType(); + // if the pattern types are the same + if (patternType == otherPatternType) { + // if the type is PATH + if (patternType == MatchableURLPattern.PATH) { + int otherPathLength = otherPattern.getPathLength(); + // if path lengths are different, the pattern with longer path length should be first + if (pathLength != otherPathLength) { + return (otherPathLength - pathLength); + // path length are the same, the pattern with the smaller order should be first + } else { + return (order - otherPattern.getOrder()); + } + // for EXACT or EXTENSION, the pattern with the smaller order should be first + } else { + return (order - otherPattern.getOrder()); + } + } else { + // pattern types are not the same, order should be EXACT, PATH, EXTENSION + return (patternType - otherPatternType); + } + } + } + + /** + * Get the path length of the pattern. This is only valid when getPatternType() = PATH.

+ * Examples: + *

+ * + * @return path length of this pattern + */ + public int getPathLength() { + return pathLength; + } + + /** + * Initialize pattern-related internal variables. + * + * @param compiler an RECompiler + * + * @exception RESyntaxException + */ + private void init(RECompiler compiler) throws RESyntaxException { + // calculate the path length + pathLength = -1; + int pos = pattern.indexOf('/'); + while (pos != -1) { + pathLength++; + pos = pattern.indexOf('/', pos + 1); + } + // determine the pattern type + if (pattern.startsWith("*.")) { + patternType = MatchableURLPattern.EXTENSION; + } else if (pattern.startsWith("/") && pattern.endsWith("/*")) { + patternType = MatchableURLPattern.PATH; + } else { + patternType = MatchableURLPattern.EXACT; + } + // initilize the patternRE + if (compiler == null) { + compiler = new RECompiler(); } + patternRE = new RE(compiler.compile(getConvertedPattern())); } /** diff --git a/src/share/org/securityfilter/filter/SavedRequest.java b/src/share/org/securityfilter/filter/SavedRequest.java index f88089f..07acc7f 100644 --- a/src/share/org/securityfilter/filter/SavedRequest.java +++ b/src/share/org/securityfilter/filter/SavedRequest.java @@ -1,7 +1,7 @@ /* - * $Header: /cvsroot/securityfilter/securityfilter/src/share/org/securityfilter/filter/SavedRequest.java,v 1.1 2002/08/12 01:34:28 maxcooper Exp $ - * $Revision: 1.1 $ - * $Date: 2002/08/12 01:34:28 $ + * $Header: /cvsroot/securityfilter/securityfilter/src/share/org/securityfilter/filter/SavedRequest.java,v 1.2 2002/08/14 13:13:23 maxcooper Exp $ + * $Revision: 1.2 $ + * $Date: 2002/08/14 13:13:23 $ * * ==================================================================== * The SecurityFilter Software License, Version 1.1 @@ -56,14 +56,17 @@ package org.securityfilter.filter; import javax.servlet.http.HttpServletRequest; +import java.io.Serializable; import java.util.Map; /** - * SavedRequest + * SavedRequest represents a request that initiated an authorization sequence. + * It saves the parameterMap and (HTTP) Method of the original request to be used after the user is authenticated + * and the original request information is needed for processing. * * @author Max Cooper (max@maxcooper.com) */ -public class SavedRequest { +public class SavedRequest implements Serializable { private Map parameterMap; private String method; diff --git a/src/share/org/securityfilter/filter/SecurityFilter.java b/src/share/org/securityfilter/filter/SecurityFilter.java index e7369b0..2817f6f 100644 --- a/src/share/org/securityfilter/filter/SecurityFilter.java +++ b/src/share/org/securityfilter/filter/SecurityFilter.java @@ -1,7 +1,7 @@ /* - * $Header: /cvsroot/securityfilter/securityfilter/src/share/org/securityfilter/filter/SecurityFilter.java,v 1.4 2002/08/12 02:08:54 maxcooper Exp $ - * $Revision: 1.4 $ - * $Date: 2002/08/12 02:08:54 $ + * $Header: /cvsroot/securityfilter/securityfilter/src/share/org/securityfilter/filter/SecurityFilter.java,v 1.5 2002/08/14 13:13:23 maxcooper Exp $ + * $Revision: 1.5 $ + * $Date: 2002/08/14 13:13:23 $ * * ==================================================================== * The SecurityFilter Software License, Version 1.1 @@ -78,7 +78,7 @@ import java.util.*; * * @author Max Cooper (max@maxcooper.com) * @author Torgeir Veimo (torgeir@pobox.com) - * @version $Revision: 1.4 $ $Date: 2002/08/12 02:08:54 $ + * @version $Revision: 1.5 $ $Date: 2002/08/14 13:13:23 $ */ public class SecurityFilter implements Filter { public static final String SAVED_REQUEST_URL = SecurityFilter.class.getName() + ".SAVED_REQUEST_URL"; @@ -231,6 +231,11 @@ public class SecurityFilter implements Filter { } } Collections.sort(patternList); + //System.out.println("Sorted pattern list:"); + //for (Iterator i = patternList.iterator(); i.hasNext(); ) { + // MatchableURLPattern pattern = (MatchableURLPattern) i.next(); + // System.out.println(pattern.getPattern()); + //} } catch (RESyntaxException rese) { System.err.println("invalid regular expression pattern: " + rese); diff --git a/src/share/org/securityfilter/realm/SimplePrincipal.java b/src/share/org/securityfilter/realm/SimplePrincipal.java new file mode 100644 index 0000000..c781b81 --- /dev/null +++ b/src/share/org/securityfilter/realm/SimplePrincipal.java @@ -0,0 +1,126 @@ +/* + * $Header: /cvsroot/securityfilter/securityfilter/src/share/org/securityfilter/realm/SimplePrincipal.java,v 1.1 2002/08/14 13:13:56 maxcooper Exp $ + * $Revision: 1.1 $ + * $Date: 2002/08/14 13:13:56 $ + * + * ==================================================================== + * The SecurityFilter Software License, Version 1.1 + * + * (this license is derived and fully compatible with the Apache Software + * License - see http://www.apache.org/LICENSE.txt) + * + * Copyright (c) 2002 SecurityFilter.org. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by + * SecurityFilter.org (http://www.securityfilter.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The name "SecurityFilter" must not be used to endorse or promote + * products derived from this software without prior written permission. + * For written permission, please contact license@securityfilter.org . + * + * 5. Products derived from this software may not be called "SecurityFilter", + * nor may "SecurityFilter" appear in their name, without prior written + * permission of SecurityFilter.org. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + */ + +package org.securityfilter.realm; + +import java.io.Serializable; +import java.security.Principal; + +/** + * SimplePrincipal - a simple, serializable Principal. + * + * @author Max Cooper (max@maxcooper.com) + */ +public class SimplePrincipal implements Principal, Serializable { + + private String name; + + /** + * Default constructor is private. Use SimplePrincipal(String name) constructor. + */ + private SimplePrincipal() { + } + + /** + * Constructor + */ + public SimplePrincipal(String name) { + this.name = name; + } + + /** + * Returns the name of this principal. + * + * @return the name of this principal. + */ + public String getName() { + return name; + } + + /** + * Compares this principal to the specified object. + * + * @param obj object to compare with. + * + * @return true if the object passed in is a SimplePrincipal with the same name. + */ + public boolean equals(Object obj) { + if (obj instanceof SimplePrincipal) { + return name.equals(((SimplePrincipal)obj).getName()); + } + return false; + } + + /** + * Returns a string representation of this principal. + * + * @return a string representation of this principal. + */ + public String toString() { + return "SimplePrincipal[name = \'" + name + "\']"; + } + + /** + * Returns a hashcode for this principal. + * + * @return a hashcode for this principal. + */ + public int hashCode() { + return name.hashCode(); + } +} + +// ---------------------------------------------------------------------------- +// EOF \ No newline at end of file diff --git a/src/share/org/securityfilter/realm/SimpleSecurityRealmBase.java b/src/share/org/securityfilter/realm/SimpleSecurityRealmBase.java index 9032951..3d14929 100644 --- a/src/share/org/securityfilter/realm/SimpleSecurityRealmBase.java +++ b/src/share/org/securityfilter/realm/SimpleSecurityRealmBase.java @@ -1,7 +1,7 @@ /* - * $Header: /cvsroot/securityfilter/securityfilter/src/share/org/securityfilter/realm/SimpleSecurityRealmBase.java,v 1.1 2002/08/14 11:26:31 maxcooper Exp $ - * $Revision: 1.1 $ - * $Date: 2002/08/14 11:26:31 $ + * $Header: /cvsroot/securityfilter/securityfilter/src/share/org/securityfilter/realm/SimpleSecurityRealmBase.java,v 1.2 2002/08/14 13:13:56 maxcooper Exp $ + * $Revision: 1.2 $ + * $Date: 2002/08/14 13:13:56 $ * * ==================================================================== * The SecurityFilter Software License, Version 1.1 @@ -56,6 +56,7 @@ package org.securityfilter.realm; import java.security.Principal; +import java.io.Serializable; /** * Security realm base class. This class insulates you from having to create or process Principal @@ -102,13 +103,9 @@ public class SimpleSecurityRealmBase implements SecurityRealmInterface { * * @return a Principal object representing the user if successful, false otherwise */ - public Principal authenticate(final String username, String password) { + public Principal authenticate(String username, String password) { if (booleanAuthenticate(username, password)) { - return new Principal() { - public String getName() { - return username; - } - }; + return new SimplePrincipal(username); } else { return null; } -- 2.11.0