shiro-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From lhazlew...@apache.org
Subject svn commit: r1209662 [3/3] - in /shiro/trunk: ./ core/src/main/java/org/apache/shiro/authc/credential/ core/src/main/java/org/apache/shiro/codec/ core/src/main/java/org/apache/shiro/config/ core/src/main/java/org/apache/shiro/crypto/ core/src/main/java...
Date Fri, 02 Dec 2011 19:52:40 GMT
Modified: shiro/trunk/tools/hasher/src/main/java/org/apache/shiro/tools/hasher/Hasher.java
URL: http://svn.apache.org/viewvc/shiro/trunk/tools/hasher/src/main/java/org/apache/shiro/tools/hasher/Hasher.java?rev=1209662&r1=1209661&r2=1209662&view=diff
==============================================================================
--- shiro/trunk/tools/hasher/src/main/java/org/apache/shiro/tools/hasher/Hasher.java (original)
+++ shiro/trunk/tools/hasher/src/main/java/org/apache/shiro/tools/hasher/Hasher.java Fri Dec
 2 19:52:37 2011
@@ -24,6 +24,7 @@ import org.apache.shiro.codec.Hex;
 import org.apache.shiro.crypto.SecureRandomNumberGenerator;
 import org.apache.shiro.crypto.UnknownAlgorithmException;
 import org.apache.shiro.crypto.hash.SimpleHash;
+import org.apache.shiro.crypto.hash.format.*;
 import org.apache.shiro.io.ResourceUtils;
 import org.apache.shiro.util.ByteSource;
 import org.apache.shiro.util.JavaEnvironment;
@@ -46,28 +47,30 @@ import java.util.Arrays;
  */
 public final class Hasher {
 
-    private static final Option ALGORITHM = new Option("a", "algorithm", true, "hash algorithm
name.  Defaults to MD5.");
+    private static final Option ALGORITHM = new Option("a", "algorithm", true, "hash algorithm
name.  Defaults to MD5 (SHA-256 when password hashing).");
     private static final Option DEBUG = new Option("d", "debug", false, "show additional
error (stack trace) information.");
+    private static final Option FORMAT = new Option("f", "format", true, "hash output format.
 Defaults to 'shiro1' when password hashing, 'hex' otherwise.  See below for more information.");
     private static final Option HELP = new Option("help", "help", false, "show this help
message.");
-    private static final Option HEX = new Option("h", "hex", false, "display a hex value
instead of Base64.");
-    private static final Option ITERATIONS = new Option("i", "iterations", true, "number
of hash iterations.  Defaults to 1.");
-    private static final Option NO_FORMAT = new Option("nf", "noformat", false, "turn off
output formatting.  Any generated salt will be placed after the hash separated by a space.");
+    private static final Option ITERATIONS = new Option("i", "iterations", true, "number
of hash iterations.  Defaults to 350,000 when password hashing, 1 otherwise.");
     private static final Option PASSWORD = new Option("p", "password", false, "hash a password
(disable typing echo)");
     private static final Option PASSWORD_NC = new Option("pnc", "pnoconfirm", false, "hash
a password (disable typing echo) but disable password confirmation prompt.");
     private static final Option RESOURCE = new Option("r", "resource", false, "read and hash
the resource located at <value>.  See below for more information.");
     private static final Option SALT = new Option("s", "salt", true, "use the specified salt.
 <arg> is plaintext.");
     private static final Option SALT_BYTES = new Option("sb", "saltbytes", true, "use the
specified salt bytes.  <arg> is hex or base64 encoded text.");
     private static final Option SALT_GEN = new Option("gs", "gensalt", false, "generate and
use a random salt.");
-    private static final Option SALT_GEN_HEX = new Option("gsh", "gensalthex", false, "display
the generated salt's hex value instead of Base64.");
+    private static final Option NO_SALT_GEN = new Option("ngs", "nogensalt", false, "do NOT
generate and use a random salt (valid during password hashing).");
     private static final Option SALT_GEN_SIZE = new Option("gss", "gensaltsize", true, "the
number of salt bits (not bytes!) to generate.  Defaults to 128.");
-    private static final Option SHIRO = new Option("shiro", "shiro", false, "display output
in the Shiro password file format (.ini [users] config).");
 
     private static final String HEX_PREFIX = "0x";
     private static final String DEFAULT_ALGORITHM_NAME = "MD5";
+    private static final String DEFAULT_PASSWORD_ALGORITHM_NAME = "SHA-256";
     private static final int DEFAULT_GENERATED_SALT_SIZE = 128;
     private static final int DEFAULT_NUM_ITERATIONS = 1;
+    private static final int DEFAULT_PASSWORD_NUM_ITERATIONS = 350000;
     private static final String SALT_MUTEX_MSG = createMutexMessage(SALT, SALT_BYTES);
 
+    private static final HashFormatFactory HASH_FORMAT_FACTORY = new DefaultHashFormatFactory();
+
     static {
         ALGORITHM.setArgName("name");
         SALT_GEN_SIZE.setArgName("numBits");
@@ -81,26 +84,23 @@ public final class Hasher {
         CommandLineParser parser = new PosixParser();
 
         Options options = new Options();
-        options.addOption(HELP).addOption(DEBUG).addOption(ALGORITHM).addOption(HEX).addOption(ITERATIONS);
+        options.addOption(HELP).addOption(DEBUG).addOption(ALGORITHM).addOption(ITERATIONS);
         options.addOption(RESOURCE).addOption(PASSWORD).addOption(PASSWORD_NC);
-        options.addOption(SALT).addOption(SALT_BYTES).addOption(SALT_GEN).addOption(SALT_GEN_SIZE).addOption(SALT_GEN_HEX);
-        options.addOption(NO_FORMAT).addOption(SHIRO);
+        options.addOption(SALT).addOption(SALT_BYTES).addOption(SALT_GEN).addOption(SALT_GEN_SIZE).addOption(NO_SALT_GEN);
+        options.addOption(FORMAT);
 
         boolean debug = false;
-        String algorithm = DEFAULT_ALGORITHM_NAME;
-        int iterations = DEFAULT_NUM_ITERATIONS;
-        boolean base64 = true;
+        String algorithm = null; //user unspecified
+        int iterations = 0; //0 means unspecified by the end-user
         boolean resource = false;
         boolean password = false;
         boolean passwordConfirm = true;
         String saltString = null;
         String saltBytesString = null;
         boolean generateSalt = false;
-        boolean generatedSaltBase64 = true;
         int generatedSaltSize = DEFAULT_GENERATED_SALT_SIZE;
 
-        boolean shiroFormat = false;
-        boolean format = true;
+        String formatString = null;
 
         char[] passwordChars = null;
 
@@ -119,17 +119,16 @@ public final class Hasher {
             if (line.hasOption(ITERATIONS.getOpt())) {
                 iterations = getRequiredPositiveInt(line, ITERATIONS);
             }
-            if (line.hasOption(HEX.getOpt())) {
-                base64 = false;
-            }
             if (line.hasOption(PASSWORD.getOpt())) {
                 password = true;
+                generateSalt = true;
             }
             if (line.hasOption(RESOURCE.getOpt())) {
                 resource = true;
             }
             if (line.hasOption(PASSWORD_NC.getOpt())) {
                 password = true;
+                generateSalt = true;
                 passwordConfirm = false;
             }
             if (line.hasOption(SALT.getOpt())) {
@@ -138,12 +137,11 @@ public final class Hasher {
             if (line.hasOption(SALT_BYTES.getOpt())) {
                 saltBytesString = line.getOptionValue(SALT_BYTES.getOpt());
             }
-            if (line.hasOption(SALT_GEN.getOpt())) {
-                generateSalt = true;
+            if (line.hasOption(NO_SALT_GEN.getOpt())) {
+                generateSalt = false;
             }
-            if (line.hasOption(SALT_GEN_HEX.getOpt())) {
+            if (line.hasOption(SALT_GEN.getOpt())) {
                 generateSalt = true;
-                generatedSaltBase64 = false;
             }
             if (line.hasOption(SALT_GEN_SIZE.getOpt())) {
                 generateSalt = true;
@@ -152,14 +150,11 @@ public final class Hasher {
                     throw new IllegalArgumentException("Generated salt size must be a multiple
of 8 (e.g. 128, 192, 256, 512, etc).");
                 }
             }
-            if (line.hasOption(NO_FORMAT.getOpt())) {
-                format = false;
-            }
-            if (line.hasOption(SHIRO.getOpt())) {
-                shiroFormat = true;
+            if (line.hasOption(FORMAT.getOpt())) {
+                formatString = line.getOptionValue(FORMAT.getOpt());
             }
 
-            String sourceValue = null;
+            String sourceValue;
 
             Object source;
 
@@ -186,19 +181,45 @@ public final class Hasher {
                 }
             }
 
+            if (algorithm == null) {
+                if (password) {
+                    algorithm = DEFAULT_PASSWORD_ALGORITHM_NAME;
+                } else {
+                    algorithm = DEFAULT_ALGORITHM_NAME;
+                }
+            }
+
+            if (iterations < DEFAULT_NUM_ITERATIONS) {
+                //Iterations were not specified.  Default to 350,000 when password hashing,
and 1 for everything else:
+                if (password) {
+                    iterations = DEFAULT_PASSWORD_NUM_ITERATIONS;
+                } else {
+                    iterations = DEFAULT_NUM_ITERATIONS;
+                }
+            }
+
             ByteSource salt = getSalt(saltString, saltBytesString, generateSalt, generatedSaltSize);
 
             SimpleHash hash = new SimpleHash(algorithm, source, salt, iterations);
 
-            StringBuilder output;
-            if (shiroFormat) {
-                output = formatForShiroIni(hash, base64, salt, generatedSaltBase64, generateSalt);
-            } else if (format) {
-                output = format(hash, base64, salt, generatedSaltBase64, generateSalt, algorithm,
sourceValue);
-            } else {
-                output = formatMinimal(hash, base64, salt, generatedSaltBase64, generateSalt);
+            if (formatString == null) {
+                //Output format was not specified.  Default to 'shiro1' when password hashing,
and 'hex' for
+                //everything else:
+                if (password) {
+                    formatString = Shiro1CryptFormat.class.getName();
+                } else {
+                    formatString = HexFormat.class.getName();
+                }
+            }
+
+            HashFormat format = HASH_FORMAT_FACTORY.getInstance(formatString);
+
+            if (format == null) {
+                throw new IllegalArgumentException("Unrecognized hash format '" + formatString
+ "'.");
             }
 
+            String output = format.format(hash);
+
             System.out.println(output);
 
         } catch (IllegalArgumentException iae) {
@@ -238,72 +259,6 @@ public final class Hasher {
         System.exit(-1);
     }
 
-    private static StringBuilder format(ByteSource hash, boolean hashBase64, ByteSource salt,
boolean saltBase64, boolean showSalt, String alg, String value) {
-        StringBuilder sb = new StringBuilder();
-
-        sb.append(alg).append("(").append(value).append(")");
-
-        if (hashBase64) {
-            sb.append(" base64 = ").append(hash.toBase64());
-        } else {
-            sb.append(" hex = ").append(hash.toHex());
-        }
-
-        if (showSalt && salt != null) {
-            sb.append("\nGenerated salt");
-            if (saltBase64) {
-                sb.append(" base64 = ").append(salt.toBase64());
-            } else {
-                sb.append(" hex = ").append(salt.toHex());
-            }
-        }
-
-        return sb;
-    }
-
-    private static StringBuilder formatForShiroIni(ByteSource hash, boolean hashBase64, ByteSource
salt, boolean saltBase64, boolean showSalt) {
-        StringBuilder sb = new StringBuilder();
-
-        if (hashBase64) {
-            sb.append(hash.toBase64());
-        } else {
-            //hex:
-            sb.append(HEX_PREFIX).append(hash.toHex());
-        }
-
-        if (showSalt && salt != null) {
-            sb.append(" ");
-            if (saltBase64) {
-                sb.append(salt.toBase64());
-            } else {
-                //hex:
-                sb.append(HEX_PREFIX).append(salt.toHex());
-            }
-        }
-        return sb;
-    }
-
-    private static StringBuilder formatMinimal(ByteSource hash, boolean hashBase64, ByteSource
salt, boolean saltBase64, boolean showSalt) {
-        StringBuilder sb = new StringBuilder();
-
-        if (hashBase64) {
-            sb.append(hash.toBase64());
-        } else {
-            sb.append(hash.toHex());
-        }
-
-        if (showSalt && salt != null) {
-            sb.append(" ");
-            if (saltBase64) {
-                sb.append(salt.toBase64());
-            } else {
-                sb.append(salt.toHex());
-            }
-        }
-
-        return sb;
-    }
-
     private static int getRequiredPositiveInt(CommandLine line, Option option) {
         String iterVal = line.getOptionValue(option.getOpt());
         try {
@@ -387,7 +342,6 @@ public final class Hasher {
                 "---------------------------------\n" +
                 "Specifying a salt:" +
                 "\n\n" +
-
                 "You may specify a salt using the -s/--salt option followed by the salt\n"
+
                 "value.  If the salt value is a base64 or hex string representing a\n" +
                 "byte array, you must specify the -sb/--saltbytes option to indicate this,\n"
+
@@ -401,9 +355,9 @@ public final class Hasher {
                 "\n\n" +
                 "Use the -sg/--saltgenerated option if you don't want to specify a salt,\n"
+
                 "but want a strong random salt to be generated and used during hashing.\n"
+
-                "The generated salt size defaults to 128 bytes.  You may specify\n" +
+                "The generated salt size defaults to 128 bits.  You may specify\n" +
                 "a different size by using the -sgs/--saltgeneratedsize option followed by\n"
+
-                "a positive integer." +
+                "a positive integer (size is in bits, not bytes)." +
                 "\n\n" +
                 "Because a salt must be specified if computing the\n" +
                 "hash later, generated salts will be printed, defaulting to base64\n" +
@@ -424,7 +378,18 @@ public final class Hasher {
                 "<command> -r ~/documents/myfile.pdf\n" +
                 "<command> -r /usr/local/logs/absolutePathFile.log\n" +
                 "<command> -r url:http://foo.com/page.html\n" +
-                "<command> -r classpath:/WEB-INF/lib/something.jar";
+                "<command> -r classpath:/WEB-INF/lib/something.jar" +
+                "\n\n" +
+                "Output Format:\n" +
+                "---------------------------------\n" +
+                "Specify the -f/--format option followed by either 1) the format ID (as defined\n"
+
+                "by the " + DefaultHashFormatFactory.class.getName() + "\n" +
+                "JavaDoc) or 2) the fully qualified " + HashFormat.class.getName() + "\n"
+
+                "implementation class name to instantiate and use for formatting.\n\n" +
+                "The default output format is 'shiro1' which is a Modular Crypt Format (MCF)\n"
+
+                "that shows all relevant information as a dollar-sign ($) delimited string.\n"
+
+                "This format is ideal for use in Shiro's text-based user configuration (e.g.\n"
+
+                "shiro.ini or a properties file).";
 
         printException(e, debug);
 

Modified: shiro/trunk/web/src/main/java/org/apache/shiro/web/env/DefaultWebEnvironment.java
URL: http://svn.apache.org/viewvc/shiro/trunk/web/src/main/java/org/apache/shiro/web/env/DefaultWebEnvironment.java?rev=1209662&r1=1209661&r2=1209662&view=diff
==============================================================================
--- shiro/trunk/web/src/main/java/org/apache/shiro/web/env/DefaultWebEnvironment.java (original)
+++ shiro/trunk/web/src/main/java/org/apache/shiro/web/env/DefaultWebEnvironment.java Fri
Dec  2 19:52:37 2011
@@ -42,11 +42,11 @@ public class DefaultWebEnvironment exten
     }
 
     public FilterChainResolver getFilterChainResolver() {
-        return (FilterChainResolver)this.objects.get(DEFAULT_FILTER_CHAIN_RESOLVER_NAME);
+        return getObject(DEFAULT_FILTER_CHAIN_RESOLVER_NAME, FilterChainResolver.class);
     }
 
     public void setFilterChainResolver(FilterChainResolver filterChainResolver) {
-        this.objects.put(DEFAULT_FILTER_CHAIN_RESOLVER_NAME, filterChainResolver);
+        setObject(DEFAULT_FILTER_CHAIN_RESOLVER_NAME, filterChainResolver);
     }
 
     @Override

Modified: shiro/trunk/web/src/test/java/org/apache/shiro/web/mgt/CookieRememberMeManagerTest.java
URL: http://svn.apache.org/viewvc/shiro/trunk/web/src/test/java/org/apache/shiro/web/mgt/CookieRememberMeManagerTest.java?rev=1209662&r1=1209661&r2=1209662&view=diff
==============================================================================
--- shiro/trunk/web/src/test/java/org/apache/shiro/web/mgt/CookieRememberMeManagerTest.java
(original)
+++ shiro/trunk/web/src/test/java/org/apache/shiro/web/mgt/CookieRememberMeManagerTest.java
Fri Dec  2 19:52:37 2011
@@ -35,13 +35,10 @@ import javax.servlet.http.HttpServletReq
 import javax.servlet.http.HttpServletResponse;
 
 import static org.easymock.EasyMock.*;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.*;
 
 /**
- * TODO - Class JavaDoc
+ * Unit tests for the {@link CookieRememberMeManager} implementation.
  *
  * @since 1.0
  */
@@ -125,13 +122,13 @@ public class CookieRememberMeManagerTest
 
         //The following base64 string was determined from the log output of the above 'onSuccessfulLogin'
test.
         //This will have to change any time the PrincipalCollection implementation changes:
-        final String userPCAesBase64 = "qk7spFqO1zoNLgq3qArE7bc8+J+Zvm1jz8lDSUmRiRlDQQx7jxG4+"
+
-                "QImiRpR7zO0d9oHH+7C3VeN9OvGMdjxtpbInMsLcGz4Q0u3M1fmyErn5Mr61chmNzQ8cLegpIKE3M+xMY"
+
-                "5JB1PRw7aEJdRxtHh80kiXZ5jeALvDP3hmFM7OF2CDKLIIa83XuBQvyrKGI9GhsxGTLkmNFknbfRsmN7v"
+
-                "NIDorceeaMkAetYf6GxDOw1ZK7yEbsydIHnqVWNHLen6DHC8pLkqMNOoGwXLeBroD6mRpoFf76J0VKBcd"
+
-                "C54Mg73S2R7wx9ZzSNJJrCi1KAilmThzm3Rm97EidUnYlWI0TM+zvMzNsLynIK4PoIG6HYQQfEI35qVRI"
+
-                "bCdbTlTnjfM/fPf7RWO8s4Z7KzszSQMJE9LgBudcyzrld5ZrWb11cianskNZMI8kzOITezjjqvWn5U4jg"
+
-                "Mb9a6qcpaNJcgaxV6NZRmof8cnet54wwE=";
+        final String userPCAesBase64 = "WlD5MLzzZznN3dQ1lPJO/eScSuY245k29aECNmjUs31o7Yu478hWhaM5Sj"
+
+                "jmoe900/72JNu3hcJaPG6Q17Vuz4F8x0kBjbFnPVx4PqzsZYT6yreeS2jwO6OwfI+efqXOKyB2a5KPtnr"
+
+                "7jt5kZsyH38XJISb81cf6xqTGUru8zC+kNqJFz7E5RpO0kraBofS5jhMm45gDVjDRkjgPJAzocVWMtrza"
+
+                "zy67P8eb+kMSBCqGI251JTNAGboVgQ28KjfaAJ/6LXRJUj7kB7CGia7mgRk+hxzEJGDs81at5VOPqODJr"
+
+                "xb8tcIdemFUFIkiYVP9bGs4dP3ECtmw7aNrCzv+84sx3vRFUrd5DbDYpEuE12hF2Y9owDK9sxStbXoF0y"
+
+                "A32dhfGDIqS+agsass0sWn8WX2TM9i8SxrUjiFbxqyIG49HbqGrZp5QLM9IuIwO+TzGfF1FzumQGdwmWT"
+
+                "xkVapw5UESl34YvA615cb+82ue1I=";
 
         Cookie[] cookies = new Cookie[]{
                 new Cookie(CookieRememberMeManager.DEFAULT_REMEMBER_ME_COOKIE_NAME, userPCAesBase64)



Mime
View raw message