[java-identity-provider] branch master updated: Missed a commit.

Scott Cantor cantor.2 at osu.edu
Tue Aug 13 18:11:18 EDT 2019


This is an automated email from the git hooks/post-receive script.

scantor pushed a commit to branch master
in repository java-identity-provider.

View the commit online:
http://git.shibboleth.net/view/?p=java-identity-provider.git;a=commit;h=e3220f55d5e532016994ebc24f5b0883f84ff439

The following commit(s) were added to refs/heads/master by this push:
       new  e3220f5   Missed a commit.
e3220f5 is described below

commit e3220f55d5e532016994ebc24f5b0883f84ff439
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Tue Aug 13 18:11:16 2019 -0400

    Missed a commit.
---
 ...bstractUsernamePasswordCredentialValidator.java | 126 ++++++++++++++++++++-
 1 file changed, 123 insertions(+), 3 deletions(-)

diff --git a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/AbstractUsernamePasswordCredentialValidator.java b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/AbstractUsernamePasswordCredentialValidator.java
index f3822c3..9faf33e 100644
--- a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/AbstractUsernamePasswordCredentialValidator.java
+++ b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/AbstractUsernamePasswordCredentialValidator.java
@@ -17,7 +17,12 @@
 
 package net.shibboleth.idp.authn;
 
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
 import java.util.function.Function;
+import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import javax.annotation.Nonnull;
@@ -29,9 +34,12 @@ import net.shibboleth.idp.authn.context.AuthenticationContext;
 import net.shibboleth.idp.authn.context.UsernamePasswordContext;
 import net.shibboleth.idp.authn.principal.PasswordPrincipal;
 import net.shibboleth.idp.authn.principal.UsernamePrincipal;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
 import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+import net.shibboleth.utilities.java.support.collection.Pair;
 import net.shibboleth.utilities.java.support.component.ComponentSupport;
 import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.utilities.java.support.primitive.StringSupport;
 
 import org.opensaml.messaging.context.navigate.ChildContextLookup;
 import org.opensaml.profile.context.ProfileRequestContext;
@@ -64,10 +72,28 @@ public abstract class AbstractUsernamePasswordCredentialValidator extends Abstra
     /** A regular expression to apply for acceptance testing. */
     @Nullable private Pattern matchExpression;
     
+    /** Match patterns and replacement strings to apply prior to use. */
+    @Nonnull @NonnullElements private List<Pair<Pattern,String>> transforms;
+
+    /** Convert username to uppercase prior to transforms? */
+    private boolean uppercase;
+    
+    /** Convert username to lowercase prior to transforms? */
+    private boolean lowercase;
+    
+    /** Trim username prior to transforms? */
+    private boolean trim;
+    
     /** Constructor. */
     public AbstractUsernamePasswordCredentialValidator() {
         usernamePasswordContextLookupStrategy = new ChildContextLookup<>(UsernamePasswordContext.class);
         removeContextAfterValidation = true;
+
+        transforms = Collections.emptyList();
+        
+        uppercase = false;
+        lowercase = false;
+        trim = false;
     }
     
     /**
@@ -138,6 +164,56 @@ public abstract class AbstractUsernamePasswordCredentialValidator extends Abstra
         matchExpression = expression;
     }
     
+    /**
+     * A collection of regular expression and replacement pairs.
+     * 
+     * @param newTransforms collection of replacement transforms
+     */
+    public void setTransforms(@Nonnull @NonnullElements final Collection<Pair<String, String>> newTransforms) {
+        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+        Constraint.isNotNull(newTransforms, "Transforms collection cannot be null");
+        
+        transforms = new ArrayList();
+        for (final Pair<String,String> p : newTransforms) {
+            final Pattern pattern = Pattern.compile(StringSupport.trimOrNull(p.getFirst()));
+            transforms.add(new Pair(pattern, Constraint.isNotNull(
+                    StringSupport.trimOrNull(p.getSecond()), "Replacement expression cannot be null")));
+        }
+    }
+
+    /**
+     * Controls conversion to uppercase prior to applying any transforms.
+     * 
+     * @param flag  uppercase flag
+     */
+    public void setUppercase(final boolean flag) {
+        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+        
+        uppercase = flag;
+    }
+
+    /**
+     * Controls conversion to lowercase prior to applying any transforms.
+     * 
+     * @param flag lowercase flag
+     */
+    public void setLowercase(final boolean flag) {
+        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+        
+        lowercase = flag;
+    }
+    
+    /**
+     * Controls whitespace trimming prior to applying any transforms.
+     * 
+     * @param flag trim flag
+     */
+    public void setTrim(final boolean flag) {
+        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+        
+        trim = flag;
+    }
+    
     /** {@inheritDoc} */
     @Override
     protected Subject doValidate(@Nonnull final ProfileRequestContext profileRequestContext,
@@ -169,8 +245,10 @@ public abstract class AbstractUsernamePasswordCredentialValidator extends Abstra
             throw new LoginException(AuthnEventIds.INVALID_CREDENTIALS);
         }
         
-        if (matchExpression != null && !matchExpression.matcher(upContext.getUsername()).matches()) {
-            log.debug("{} Username '{}' did not match expression", getLogPrefix(), upContext.getUsername());
+        upContext.setTransformedUsername(applyTransforms(upContext.getUsername()));
+        
+        if (matchExpression != null && !matchExpression.matcher(upContext.getTransformedUsername()).matches()) {
+            log.debug("{} Username '{}' did not match expression", getLogPrefix(), upContext.getTransformedUsername());
             return null;
         }
                 
@@ -180,6 +258,9 @@ public abstract class AbstractUsernamePasswordCredentialValidator extends Abstra
     /**
      * Override method for subclasses to use to perform the actual validation.
      * 
+     * <p>Any configured transforms will have been applied to populate the context with a transformed
+     * username prior to this method call.</p>
+     * 
      * @param profileRequestContext profile request context
      * @param authenticationContext authentication context
      * @param usernamePasswordContext the username/password to validate
@@ -207,7 +288,7 @@ public abstract class AbstractUsernamePasswordCredentialValidator extends Abstra
      */
     @Nonnull protected Subject populateSubject(@Nonnull final Subject subject,
             @Nonnull final UsernamePasswordContext usernamePasswordContext) {
-        subject.getPrincipals().add(new UsernamePrincipal(usernamePasswordContext.getUsername()));
+        subject.getPrincipals().add(new UsernamePrincipal(usernamePasswordContext.getTransformedUsername()));
         if (savePasswordToCredentialSet) {
             subject.getPrivateCredentials().add(new PasswordPrincipal(usernamePasswordContext.getPassword()));
         }
@@ -220,4 +301,43 @@ public abstract class AbstractUsernamePasswordCredentialValidator extends Abstra
         return super.populateSubject(subject);
     }
     
+    /**
+     * Apply any configured regular expression replacements to an input value and return the result.
+     * 
+     * @param input the input string
+     * 
+     * @return  the result of applying the expressions
+     */
+    @Nonnull @NotEmpty protected String applyTransforms(@Nonnull @NotEmpty final String input) {
+        
+        String s = input;
+        
+        if (trim) {
+            log.trace("{} Trimming whitespace of input string '{}'", getLogPrefix(), s);
+            s = s.trim();
+        }
+        
+        if (lowercase) {
+            log.trace("{} Converting input string '{}' to lowercase", getLogPrefix(), s);
+            s = s.toLowerCase();
+        } else if (uppercase) {
+            log.trace("{} Converting input string '{}' to uppercase", getLogPrefix(), s);
+            s = s.toUpperCase();
+        }
+        
+        if (transforms.isEmpty()) {
+            return s;
+        }
+        
+        for (final Pair<Pattern,String> p : transforms) {            
+            final Matcher m = p.getFirst().matcher(s);
+            log.trace("{} Applying replacement expression '{}' against input '{}'", getLogPrefix(),
+                    p.getFirst().pattern(), s);
+            s = m.replaceAll(p.getSecond());
+            log.trace("{} Result of replacement is '{}'", getLogPrefix(), s);
+        }
+        
+        return s;
+    }
+
 }
\ No newline at end of file

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list