From melissadiaz@example.net Fri Jun 3 14:52:30 2011 Return-Path: <melissadiaz@example.net> X-Original-To: melissadiaz@example.net Delivered-To: melissadiaz@example.net Received: from mail.apache.org (hermes.apache.org [83.161.120.155]) by minotaur.apache.org (Postfix) with SMTP id 289D96444 for <melissadiaz@example.net>; Fri, 3 Jun 2011 14:52:30 +0000 (UTC) Received: (qmail 87910 invoked by uid 500); 3 Jun 2011 14:52:30 -0000 Delivered-To: melissadiaz@example.net Received: (qmail 87886 invoked by uid 500); 3 Jun 2011 14:52:29 -0000 Mailing-List: contact melissadiaz@example.net; run by ezmlm Precedence: bulk List-Help: <mailto:melissadiaz@example.net> List-Unsubscribe: <mailto:melissadiaz@example.net> List-Post: <mailto:melissadiaz@example.net> List-Id: <commits.shiro.apache.org> Reply-To: melissadiaz@example.net Delivered-To: mailing list melissadiaz@example.net Received: (qmail 87879 invoked by uid 99); 3 Jun 2011 14:52:29 -0000 Received: from nike.apache.org (HELO nike.apache.org) (83.161.120.155) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 03 Jun 2011 14:52:29 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [83.161.120.155] (HELO eris.apache.org) (83.161.120.155) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 03 Jun 2011 14:52:26 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 525F123889E1; Fri, 3 Jun 2011 14:52:05 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1131059 - in /shiro/trunk/core/src: main/java/org/apache/shiro/crypto/hash/DefaultHasher.java test/java/org/apache/shiro/crypto/hash/ test/java/org/apache/shiro/crypto/hash/DefaultHasherTest.java Date: Fri, 03 Jun 2011 14:52:05 -0000 To: melissadiaz@example.net From: melissadiaz@example.net X-Mailer: svnmailer-1.0.8 Message-Id: <melissadiaz@example.net> X-Virus-Checked: Checked by ClamAV on apache.org Author: kaosko Date: Fri Jun 3 14:52:04 2011 New Revision: 1131059 URL: http://svn.apache.org/viewvc?rev=1131059&view=rev Log: FIXED - issue SHIRO-302: DefaultHasher does not generate random salt https://issues.apache.org/jira/browse/SHIRO-302 - apply Maria Jurcovicova's patch as is, including unit tests Added: shiro/trunk/core/src/test/java/org/apache/shiro/crypto/hash/ shiro/trunk/core/src/test/java/org/apache/shiro/crypto/hash/DefaultHasherTest.java Modified: shiro/trunk/core/src/main/java/org/apache/shiro/crypto/hash/DefaultHasher.java Modified: shiro/trunk/core/src/main/java/org/apache/shiro/crypto/hash/DefaultHasher.java URL: http://svn.apache.org/viewvc/shiro/trunk/core/src/main/java/org/apache/shiro/crypto/hash/DefaultHasher.java?rev=1131059&r1=1131058&r2=1131059&view=diff ============================================================================== --- shiro/trunk/core/src/main/java/org/apache/shiro/crypto/hash/DefaultHasher.java (original) +++ shiro/trunk/core/src/main/java/org/apache/shiro/crypto/hash/DefaultHasher.java Fri Jun 3 14:52:04 2011 @@ -153,7 +153,7 @@ public class DefaultHasher implements Co publicSaltBytes = null; } if (publicSaltBytes == null) { - getRandomNumberGenerator().nextBytes().getBytes(); + publicSaltBytes = getRandomNumberGenerator().nextBytes().getBytes(); } String algorithmName = getHashAlgorithmName(); Added: shiro/trunk/core/src/test/java/org/apache/shiro/crypto/hash/DefaultHasherTest.java URL: http://svn.apache.org/viewvc/shiro/trunk/core/src/test/java/org/apache/shiro/crypto/hash/DefaultHasherTest.java?rev=1131059&view=auto ============================================================================== --- shiro/trunk/core/src/test/java/org/apache/shiro/crypto/hash/DefaultHasherTest.java (added) +++ shiro/trunk/core/src/test/java/org/apache/shiro/crypto/hash/DefaultHasherTest.java Fri Jun 3 14:52:04 2011 @@ -0,0 +1,154 @@ +package org.apache.shiro.crypto.hash; + +import java.util.Arrays; + +import junit.framework.TestCase; + +import org.apache.shiro.crypto.SecureRandomNumberGenerator; +import org.apache.shiro.util.ByteSource; +import org.junit.Test; + +/** + * Test for {@link DefaultHasher} class. + * + */ +public class DefaultHasherTest { + + /** + * If the same string is hashed twice and no salt was supplied, hashed + * result should be different in each case. + */ + @Test + public void testOnlyRandomSaltRandomness() { + Hasher hasher = createHasher(); + + HashResponse firstHash = hashString(hasher, "password"); + HashResponse secondHash = hashString(hasher, "password"); + + assertNotEquals(firstHash.getHash().toBase64(), secondHash.getHash().toBase64()); + } + + /** + * If a string is hashed and no salt was supplied, random salt is generated. + * Hash of the same string with generated random salt should return the + * same result. + */ + @Test + public void testOnlyRandomSaltReturn() { + Hasher hasher = createHasher(); + + HashResponse firstHash = hashString(hasher, "password"); + HashResponse secondHash = hashString(hasher, "password", firstHash.getSalt().getBytes()); + + TestCase.assertEquals(firstHash.getHash().toBase64(), secondHash.getHash().toBase64()); + } + + /** + * Two different strings hashed with the same salt should result in two different + * hashes. + */ + @Test + public void testOnlyRandomSaltHash() { + Hasher hasher = createHasher(); + + HashResponse firstHash = hashString(hasher, "password"); + HashResponse secondHash = hashString(hasher, "password2", firstHash.getSalt().getBytes()); + + assertNotEquals(firstHash.getHash().toBase64(), secondHash.getHash().toBase64()); + } + + /** + * If the same string is hashed twice and only base salt was supplied, hashed + * result should be different in each case. + */ + @Test + public void testBothSaltsRandomness() { + Hasher hasher = createHasherWithSalt(); + + HashResponse firstHash = hashString(hasher, "password"); + HashResponse secondHash = hashString(hasher, "password"); + + assertNotEquals(firstHash.getHash().toBase64(), secondHash.getHash().toBase64()); + } + + /** + * If a string is hashed and only base salt was supplied, random salt is generated. + * Hash of the same string with generated random salt should return the + * same result. + */ + @Test + public void testBothSaltsReturn() { + Hasher hasher = createHasherWithSalt(); + + HashResponse firstHash = hashString(hasher, "password"); + HashResponse secondHash = hashString(hasher, "password", firstHash.getSalt().getBytes()); + + TestCase.assertEquals(firstHash.getHash().toBase64(), secondHash.getHash().toBase64()); + } + + /** + * Two different strings hashed with the same salt should result in two different + * hashes. + */ + @Test + public void testBothSaltsHash() { + Hasher hasher = createHasherWithSalt(); + + HashResponse firstHash = hashString(hasher, "password"); + HashResponse secondHash = hashString(hasher, "password2", firstHash.getSalt().getBytes()); + + assertNotEquals(firstHash.getHash().toBase64(), secondHash.getHash().toBase64()); + } + + /** + * Hash result is different if the base salt is added. + */ + @Test + public void testBaseSaltChangesResult() { + Hasher saltedHasher = createHasherWithSalt(); + Hasher hasher = createHasher(); + + HashResponse firstHash = hashStringPredictable(saltedHasher, "password"); + HashResponse secondHash = hashStringPredictable(hasher, "password"); + + assertNotEquals(firstHash.getHash().toBase64(), secondHash.getHash().toBase64()); + } + + protected HashResponse hashString(Hasher hasher, String string) { + return hasher.computeHash(new SimpleHashRequest(ByteSource.Util.bytes(string))); + } + + protected HashResponse hashString(Hasher hasher, String string, byte[] salt) { + return hasher.computeHash(new SimpleHashRequest(ByteSource.Util.bytes(string), ByteSource.Util.bytes(salt))); + } + + private HashResponse hashStringPredictable(Hasher hasher, String string) { + byte[] salt = new byte[20]; + Arrays.fill(salt, (byte) 2); + return hasher.computeHash(new SimpleHashRequest(ByteSource.Util.bytes(string), ByteSource.Util.bytes(salt))); + } + + private Hasher createHasher() { + return new DefaultHasher(); + } + + private Hasher createHasherWithSalt() { + DefaultHasher defaultHasher = new DefaultHasher(); + defaultHasher.setBaseSalt((new SecureRandomNumberGenerator()).nextBytes().getBytes()); + + return defaultHasher; + } + + private void assertNotEquals(String str1, String str2) { + boolean equals = equals(str1, str2); + if (equals) + TestCase.fail("Strings are supposed to be different."); + } + + protected boolean equals(String str1, String str2) { + if (str1 == null) + return str2 == null; + + return str1.equals(str2); + } +} From melissadiaz@example.net Sat Jun 11 20:49:03 2011 Return-Path: <melissadiaz@example.net> X-Original-To: melissadiaz@example.net Delivered-To: melissadiaz@example.net Received: from mail.apache.org (hermes.apache.org [83.161.120.155]) by minotaur.apache.org (Postfix) with SMTP id 330CD6CB4 for <melissadiaz@example.net>; Sat, 11 Jun 2011 20:49:03 +0000 (UTC) Received: (qmail 63205 invoked by uid 500); 11 Jun 2011 20:49:03 -0000 Delivered-To: melissadiaz@example.net Received: (qmail 63181 invoked by uid 500); 11 Jun 2011 20:49:02 -0000 Mailing-List: contact melissadiaz@example.net; run by ezmlm Precedence: bulk List-Help: <mailto:melissadiaz@example.net> List-Unsubscribe: <mailto:melissadiaz@example.net> List-Post: <mailto:melissadiaz@example.net> List-Id: <commits.shiro.apache.org> Reply-To: melissadiaz@example.net Delivered-To: mailing list melissadiaz@example.net Received: (qmail 63174 invoked by uid 99); 11 Jun 2011 20:49:02 -0000 Received: from athena.apache.org (HELO athena.apache.org) (83.161.120.155) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 11 Jun 2011 20:49:02 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [83.161.120.155] (HELO eris.apache.org) (83.161.120.155) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 11 Jun 2011 20:49:01 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 91FE923889EC; Sat, 11 Jun 2011 20:48:41 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1134752 - /shiro/board/2011-06.txt Date: Sat, 11 Jun 2011 20:48:41 -0000 To: melissadiaz@example.net From: melissadiaz@example.net X-Mailer: svnmailer-1.0.8 Message-Id: <melissadiaz@example.net> Author: lhazlewood Date: Sat Jun 11 20:48:41 2011 New Revision: 1134752 URL: http://svn.apache.org/viewvc?rev=1134752&view=rev Log: Added initial 2011 June Board report draft. To be discussed on the dev mailing list. Added: shiro/board/2011-06.txt Added: shiro/board/2011-06.txt URL: http://svn.apache.org/viewvc/shiro/board/2011-06.txt?rev=1134752&view=auto ============================================================================== --- shiro/board/2011-06.txt (added) +++ shiro/board/2011-06.txt Sat Jun 11 20:48:41 2011 @@ -0,0 +1,36 @@ +2011 June - Board report for Apache Shiro + +Apache Shiro is a powerful and flexible open-source application security +framework that cleanly handles authentication, authorization, enterprise +session management and cryptography. + +We have no issues that require Board assistance at this time. + +Releases: +- No releases since our first 1 Nov 2010 1.1.0 release + +Community & Project: + + This last quarter has been focused more on community building than + coding, with great success. The Shiro average website visitor traffic + has increased more than half (59%) in only 3 months! We continue to + grow and help the Java security community. Following are + the most important points from the last quarter. + + - The Apache Shiro team is excited to report that we have added + Brian Demers as our first new committer after becoming a TLP. We're + excited that our community continues to grow with quality folks like + Brian. + + - There has been minor discussion of creating a 1.2 release soon. A + few minor issues need to be resolved, and hopefully this will be done + before our next board report. + + - While Shiro doesn't receive many complaints, the most frequent one has + been that non-JavaDoc documentation has been lacking. Significant work + has gone into improving Shiro's documentation over the last month, and + we believe this will serve the community much better. + + - To improve project publicity, Les Hazlewood wrote an intro article on + Apache Shiro published on InfoQ: http://www.infoq.com/articles/apache-shiro + This has contributed to site traffic and community adoption significantly. \ No newline at end of file From melissadiaz@example.net Sat Jun 11 21:02:37 2011 Return-Path: <melissadiaz@example.net> X-Original-To: melissadiaz@example.net Delivered-To: melissadiaz@example.net Received: from mail.apache.org (hermes.apache.org [83.161.120.155]) by minotaur.apache.org (Postfix) with SMTP id BF5E86C51 for <melissadiaz@example.net>; Sat, 11 Jun 2011 21:02:37 +0000 (UTC) Received: (qmail 71486 invoked by uid 500); 11 Jun 2011 21:02:37 -0000 Delivered-To: melissadiaz@example.net Received: (qmail 71461 invoked by uid 500); 11 Jun 2011 21:02:37 -0000 Mailing-List: contact melissadiaz@example.net; run by ezmlm Precedence: bulk List-Help: <mailto:melissadiaz@example.net> List-Unsubscribe: <mailto:melissadiaz@example.net> List-Post: <mailto:melissadiaz@example.net> List-Id: <commits.shiro.apache.org> Reply-To: melissadiaz@example.net Delivered-To: mailing list melissadiaz@example.net Received: (qmail 71454 invoked by uid 99); 11 Jun 2011 21:02:37 -0000 Received: from nike.apache.org (HELO nike.apache.org) (83.161.120.155) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 11 Jun 2011 21:02:37 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [83.161.120.155] (HELO eris.apache.org) (83.161.120.155) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 11 Jun 2011 21:02:35 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 7E91E23889EC; Sat, 11 Jun 2011 21:02:14 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1134755 - /shiro/trunk/core/src/main/java/org/apache/shiro/crypto/RandomNumberGenerator.java Date: Sat, 11 Jun 2011 21:02:14 -0000 To: melissadiaz@example.net From: melissadiaz@example.net X-Mailer: svnmailer-1.0.8 Message-Id: <melissadiaz@example.net> X-Virus-Checked: Checked by ClamAV on apache.org Author: lhazlewood Date: Sat Jun 11 21:02:14 2011 New Revision: 1134755 URL: http://svn.apache.org/viewvc?rev=1134755&view=rev Log: Minor JavaDoc fix Modified: shiro/trunk/core/src/main/java/org/apache/shiro/crypto/RandomNumberGenerator.java Modified: shiro/trunk/core/src/main/java/org/apache/shiro/crypto/RandomNumberGenerator.java URL: http://svn.apache.org/viewvc/shiro/trunk/core/src/main/java/org/apache/shiro/crypto/RandomNumberGenerator.java?rev=1134755&r1=1134754&r2=1134755&view=diff ============================================================================== --- shiro/trunk/core/src/main/java/org/apache/shiro/crypto/RandomNumberGenerator.java (original) +++ shiro/trunk/core/src/main/java/org/apache/shiro/crypto/RandomNumberGenerator.java Sat Jun 11 21:02:14 2011 @@ -32,12 +32,11 @@ import org.apache.shiro.util.ByteSource; * can be customized as necessary based on the application's needs</li> * <li>Default per-instance behavior can be customized on implementations, typically via JavaBeans mutators.</li> * <li>Perhaps most important for Shiro end-users, tt can more easily be used as a source of cryptographic seed data, - * and the data returned is already in a more {@link ByteSource ByteSource} format in case that data needs to be - * {@link org.apache.shiro.util.ByteSource#toHex() hex} or + * and the data returned is already in a more convenient {@link ByteSource ByteSource} format in case that data needs + * to be {@link org.apache.shiro.util.ByteSource#toHex() hex} or * {@link org.apache.shiro.util.ByteSource#toBase64() base64}-encoded.</li> * </ul> * For example, consider the following example generating password salts for new user accounts: - * * <pre> * RandomNumberGenerator saltGenerator = new {@link org.apache.shiro.crypto.SecureRandomNumberGenerator SecureRandomNumberGenerator}(); * User user = new User(); @@ -53,15 +52,21 @@ public interface RandomNumberGenerator { * Generates a byte array of fixed length filled with random data, often useful for generating salts, * initialization vectors or other seed data. The length is specified as a configuration * value on the underlying implementation. + * <p/> + * If you'd like per-invocation control the number of bytes generated, use the + * {@link #nextBytes(int) nextBytes(int)} method instead. * * @return a byte array of fixed length filled with random data. + * @see #nextBytes(int) */ ByteSource nextBytes(); /** * Generates a byte array of the specified length filled with random data. + * * @param numBytes the number of bytes to be populated with random data. * @return a byte array of the specified length filled with random data. + * @see #nextBytes() */ ByteSource nextBytes(int numBytes); } From melissadiaz@example.net Sat Jun 11 23:36:15 2011 Return-Path: <melissadiaz@example.net> X-Original-To: melissadiaz@example.net Delivered-To: melissadiaz@example.net Received: from mail.apache.org (hermes.apache.org [83.161.120.155]) by minotaur.apache.org (Postfix) with SMTP id AE63160AC for <melissadiaz@example.net>; Sat, 11 Jun 2011 23:36:15 +0000 (UTC) Received: (qmail 96876 invoked by uid 500); 11 Jun 2011 23:36:15 -0000 Delivered-To: melissadiaz@example.net Received: (qmail 96850 invoked by uid 500); 11 Jun 2011 23:36:15 -0000 Mailing-List: contact melissadiaz@example.net; run by ezmlm Precedence: bulk List-Help: <mailto:melissadiaz@example.net> List-Unsubscribe: <mailto:melissadiaz@example.net> List-Post: <mailto:melissadiaz@example.net> List-Id: <commits.shiro.apache.org> Reply-To: melissadiaz@example.net Delivered-To: mailing list melissadiaz@example.net Received: (qmail 96841 invoked by uid 99); 11 Jun 2011 23:36:15 -0000 Received: from nike.apache.org (HELO nike.apache.org) (83.161.120.155) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 11 Jun 2011 23:36:15 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [83.161.120.155] (HELO aegis.apache.org) (83.161.120.155) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 11 Jun 2011 23:36:13 +0000 Received: from aegis (localhost [83.161.120.155]) by aegis.apache.org (Postfix) with ESMTP id 841F1C00F5; Sat, 11 Jun 2011 23:35:52 +0000 (UTC) Date: Sat, 11 Jun 2011 23:35:43 +0000 (UTC) From: Apache Jenkins Server <melissadiaz@example.net> To: melissadiaz@example.net, melissadiaz@example.net Message-ID: <935030434.4051307835352524.JavaMail.hudson@aegis> Subject: =?UTF-8?Q?Jenkins_build_is_back_to_normal_:?= =?UTF-8?Q?_Shiro_=C2=BB_Apache_Shiro_888a:dbb7:2d49:b3f6:8605:bf4e:caed:e5a4_Core_#304?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-Virus-Checked: Checked by ClamAV on apache.org See <https://builds.apache.org/job/Shiro/org.apache.shiro$shiro-core/304/changes> From melissadiaz@example.net Tue Jun 21 17:53:06 2011 Return-Path: <melissadiaz@example.net> X-Original-To: melissadiaz@example.net Delivered-To: melissadiaz@example.net Received: from mail.apache.org (hermes.apache.org [83.161.120.155]) by minotaur.apache.org (Postfix) with SMTP id BEE154A9E for <melissadiaz@example.net>; Tue, 21 Jun 2011 17:53:06 +0000 (UTC) Received: (qmail 12426 invoked by uid 500); 21 Jun 2011 17:53:06 -0000 Delivered-To: melissadiaz@example.net Received: (qmail 12402 invoked by uid 500); 21 Jun 2011 17:53:06 -0000 Mailing-List: contact melissadiaz@example.net; run by ezmlm Precedence: bulk List-Help: <mailto:melissadiaz@example.net> List-Unsubscribe: <mailto:melissadiaz@example.net> List-Post: <mailto:melissadiaz@example.net> List-Id: <commits.shiro.apache.org> Reply-To: melissadiaz@example.net Delivered-To: mailing list melissadiaz@example.net Received: (qmail 12395 invoked by uid 99); 21 Jun 2011 17:53:06 -0000 Received: from athena.apache.org (HELO athena.apache.org) (83.161.120.155) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 21 Jun 2011 17:53:06 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [83.161.120.155] (HELO eris.apache.org) (83.161.120.155) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 21 Jun 2011 17:53:05 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id CF5482388A29; Tue, 21 Jun 2011 17:52:44 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1138107 - /shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/authc/LogoutFilter.java Date: Tue, 21 Jun 2011 17:52:44 -0000 To: melissadiaz@example.net From: melissadiaz@example.net X-Mailer: svnmailer-1.0.8 Message-Id: <melissadiaz@example.net> Author: lhazlewood Date: Tue Jun 21 17:52:44 2011 New Revision: 1138107 URL: http://svn.apache.org/viewvc?rev=1138107&view=rev Log: Added an intermediate getRedirectUrl(request,response) method to allow subclasses to dynamically configure the redirectUrl if desired. Default implementation returns getRedirectUrl() to retain current behavior. Modified: shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/authc/LogoutFilter.java Modified: shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/authc/LogoutFilter.java URL: http://svn.apache.org/viewvc/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/authc/LogoutFilter.java?rev=1138107&r1=1138106&r2=1138107&view=diff ============================================================================== --- shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/authc/LogoutFilter.java (original) +++ shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/authc/LogoutFilter.java Tue Jun 21 17:52:44 2011 @@ -59,16 +59,30 @@ public class LogoutFilter extends Advice } /** - * Issues an HTTP redirect after subject logout. This implementation calls - * {@code WebUtils.}{@link WebUtils#issueRedirect(javax.servlet.ServletRequest, javax.servlet.ServletResponse, String) issueRedirect(request,response,redirectUrl)} - * using the configured {@link #getRedirectUrl()}. + * Issues an HTTP redirect after subject logout. This implementation acquires the redirect URL returned from + * {@link #getRedirectUrl(javax.servlet.ServletRequest, javax.servlet.ServletResponse)} and then calls + * {@code WebUtils.}{@link WebUtils#issueRedirect(javax.servlet.ServletRequest, javax.servlet.ServletResponse, String) issueRedirect(request,response,redirectUrl)}. * * @param request the incoming Servlet request * @param response the outgoing Servlet response * @throws Exception if there is any error. */ protected void issueRedirect(ServletRequest request, ServletResponse response) throws Exception { - WebUtils.issueRedirect(request, response, getRedirectUrl()); + String redirectUrl = getRedirectUrl(request, response); + WebUtils.issueRedirect(request, response, redirectUrl); + } + + /** + * Returns the redirect URL to send the user after logout. This default implementation returns the static + * configured {@link #getRedirectUrl() redirectUrl} property, but this method may be overridden by subclasses + * to dynamically construct the URL if necessary. + * + * @param request the incoming Servlet request + * @param response the outgoing ServletResponse + * @return the redirect URL to send the user after logout. + */ + protected String getRedirectUrl(ServletRequest request, ServletResponse response) { + return getRedirectUrl(); } /** From melissadiaz@example.net Tue Jun 21 23:06:20 2011 Return-Path: <melissadiaz@example.net> X-Original-To: melissadiaz@example.net Delivered-To: melissadiaz@example.net Received: from mail.apache.org (hermes.apache.org [83.161.120.155]) by minotaur.apache.org (Postfix) with SMTP id E5720476A for <melissadiaz@example.net>; Tue, 21 Jun 2011 23:06:20 +0000 (UTC) Received: (qmail 63108 invoked by uid 500); 21 Jun 2011 23:06:20 -0000 Delivered-To: melissadiaz@example.net Received: (qmail 63089 invoked by uid 500); 21 Jun 2011 23:06:20 -0000 Mailing-List: contact melissadiaz@example.net; run by ezmlm Precedence: bulk List-Help: <mailto:melissadiaz@example.net> List-Unsubscribe: <mailto:melissadiaz@example.net> List-Post: <mailto:melissadiaz@example.net> List-Id: <commits.shiro.apache.org> Reply-To: melissadiaz@example.net Delivered-To: mailing list melissadiaz@example.net Received: (qmail 63082 invoked by uid 99); 21 Jun 2011 23:06:20 -0000 Received: from nike.apache.org (HELO nike.apache.org) (83.161.120.155) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 21 Jun 2011 23:06:20 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [83.161.120.155] (HELO eris.apache.org) (83.161.120.155) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 21 Jun 2011 23:06:17 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id A600C2388A29; Tue, 21 Jun 2011 23:05:56 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1138241 - /shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/authc/LogoutFilter.java Date: Tue, 21 Jun 2011 23:05:56 -0000 To: melissadiaz@example.net From: melissadiaz@example.net X-Mailer: svnmailer-1.0.8 Message-Id: <melissadiaz@example.net> X-Virus-Checked: Checked by ClamAV on apache.org Author: lhazlewood Date: Tue Jun 21 23:05:56 2011 New Revision: 1138241 URL: http://svn.apache.org/viewvc?rev=1138241&view=rev Log: Altered logic to allow the redirect url to be based on the current request or subject (before logout), falling back to a static url if necessary. Subclasses can override the template method to perform request-specific redirect URL acquisition. Modified: shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/authc/LogoutFilter.java Modified: shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/authc/LogoutFilter.java URL: http://svn.apache.org/viewvc/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/authc/LogoutFilter.java?rev=1138241&r1=1138240&r2=1138241&view=diff ============================================================================== --- shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/authc/LogoutFilter.java (original) +++ shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/authc/LogoutFilter.java Tue Jun 21 23:05:56 2011 @@ -29,8 +29,10 @@ public class LogoutFilter extends Advice private String redirectUrl = DEFAULT_REDIRECT_URL; /** - * Immediately logs out the currently executing {@link #getSubject(javax.servlet.ServletRequest, javax.servlet.ServletResponse) subject} - * and redirects the end-user to the configured {@link #getRedirectUrl() redirectUrl}. + * Acquires the currently executing {@link #getSubject(javax.servlet.ServletRequest, javax.servlet.ServletResponse) subject}, + * a potentially Subject or request-specific + * {@link #getRedirectUrl(javax.servlet.ServletRequest, javax.servlet.ServletResponse, org.apache.shiro.subject.Subject) redirectUrl}, + * and redirects the end-user to that redirect url. * * @param request the incoming ServletRequest * @param response the outgoing ServletResponse @@ -40,8 +42,9 @@ public class LogoutFilter extends Advice @Override protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception { Subject subject = getSubject(request, response); + String redirectUrl = getRedirectUrl(request, response, subject); subject.logout(); - issueRedirect(request, response); + issueRedirect(request, response, redirectUrl); return false; } @@ -59,29 +62,37 @@ public class LogoutFilter extends Advice } /** - * Issues an HTTP redirect after subject logout. This implementation acquires the redirect URL returned from - * {@link #getRedirectUrl(javax.servlet.ServletRequest, javax.servlet.ServletResponse)} and then calls + * Issues an HTTP redirect to the specified URL after subject logout. This implementation simply calls * {@code WebUtils.}{@link WebUtils#issueRedirect(javax.servlet.ServletRequest, javax.servlet.ServletResponse, String) issueRedirect(request,response,redirectUrl)}. * * @param request the incoming Servlet request * @param response the outgoing Servlet response + * @param redirectUrl the URL to where the browser will be redirected immediately after Subject logout. * @throws Exception if there is any error. */ - protected void issueRedirect(ServletRequest request, ServletResponse response) throws Exception { - String redirectUrl = getRedirectUrl(request, response); + protected void issueRedirect(ServletRequest request, ServletResponse response, String redirectUrl) throws Exception { WebUtils.issueRedirect(request, response, redirectUrl); } /** - * Returns the redirect URL to send the user after logout. This default implementation returns the static - * configured {@link #getRedirectUrl() redirectUrl} property, but this method may be overridden by subclasses - * to dynamically construct the URL if necessary. + * Returns the redirect URL to send the user after logout. This default implementation ignores the arguments and + * returns the static configured {@link #getRedirectUrl() redirectUrl} property, but this method may be overridden + * by subclasses to dynamically construct the URL based on the request or subject if necessary. + * <p/> + * Note: the Subject is <em>not</em> yet logged out at the time this method is invoked. You may access the Subject's + * session if one is available and if necessary. + * <p/> + * Tip: if you need to access the Subject's session, consider using the + * {@code Subject.}{@link Subject#getSession(boolean) getSession(false)} method to ensure a new session isn't created unnecessarily. + * If a session would be created, it will be immediately stopped after logout, not providing any value and + * unnecessarily taxing session infrastructure/resources. * * @param request the incoming Servlet request * @param response the outgoing ServletResponse + * @param subject the not-yet-logged-out currently executing Subject * @return the redirect URL to send the user after logout. */ - protected String getRedirectUrl(ServletRequest request, ServletResponse response) { + protected String getRedirectUrl(ServletRequest request, ServletResponse response, Subject subject) { return getRedirectUrl(); } From melissadiaz@example.net Thu Jun 23 23:14:28 2011 Return-Path: <melissadiaz@example.net> X-Original-To: melissadiaz@example.net Delivered-To: melissadiaz@example.net Received: from mail.apache.org (hermes.apache.org [83.161.120.155]) by minotaur.apache.org (Postfix) with SMTP id A2B3E4343 for <melissadiaz@example.net>; Thu, 23 Jun 2011 23:14:28 +0000 (UTC) Received: (qmail 89779 invoked by uid 500); 23 Jun 2011 23:14:28 -0000 Delivered-To: melissadiaz@example.net Received: (qmail 89755 invoked by uid 500); 23 Jun 2011 23:14:28 -0000 Mailing-List: contact melissadiaz@example.net; run by ezmlm Precedence: bulk List-Help: <mailto:melissadiaz@example.net> List-Unsubscribe: <mailto:melissadiaz@example.net> List-Post: <mailto:melissadiaz@example.net> List-Id: <commits.shiro.apache.org> Reply-To: melissadiaz@example.net Delivered-To: mailing list melissadiaz@example.net Received: (qmail 89746 invoked by uid 99); 23 Jun 2011 23:14:28 -0000 Received: from nike.apache.org (HELO nike.apache.org) (83.161.120.155) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 23 Jun 2011 23:14:28 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [83.161.120.155] (HELO eris.apache.org) (83.161.120.155) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 23 Jun 2011 23:14:24 +0000 Received: from eris.apache.org (localhost [83.161.120.155]) by eris.apache.org (Postfix) with ESMTP id 64C2723888BD for <melissadiaz@example.net>; Thu, 23 Jun 2011 23:14:01 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1139115 - in /shiro/trunk/core/src/main/java/org/apache/shiro: authz/permission/DomainPermission.java util/StringUtils.java Date: Thu, 23 Jun 2011 23:14:01 -0000 To: melissadiaz@example.net From: melissadiaz@example.net X-Mailer: svnmailer-1.0.8 Message-Id: <melissadiaz@example.net> X-Virus-Checked: Checked by ClamAV on apache.org Author: lhazlewood Date: Thu Jun 23 23:14:01 2011 New Revision: 1139115 URL: http://svn.apache.org/viewvc?rev=1139115&view=rev Log: SHIRO-307: Patch applied, with modifications. To be discussed further. Modified: shiro/trunk/core/src/main/java/org/apache/shiro/authz/permission/DomainPermission.java shiro/trunk/core/src/main/java/org/apache/shiro/util/StringUtils.java Modified: shiro/trunk/core/src/main/java/org/apache/shiro/authz/permission/DomainPermission.java URL: http://svn.apache.org/viewvc/shiro/trunk/core/src/main/java/org/apache/shiro/authz/permission/DomainPermission.java?rev=1139115&r1=1139114&r2=1139115&view=diff ============================================================================== --- shiro/trunk/core/src/main/java/org/apache/shiro/authz/permission/DomainPermission.java (original) +++ shiro/trunk/core/src/main/java/org/apache/shiro/authz/permission/DomainPermission.java Thu Jun 23 23:14:01 2011 @@ -20,6 +20,8 @@ package org.apache.shiro.authz.permissio import org.apache.shiro.util.StringUtils; +import java.util.Set; + /** * Provides a base Permission class from which type-safe/domain-specific subclasses may extend. Can be used * as a base class for JPA/Hibernate persisted permissions that wish to store the parts of the permission string @@ -28,28 +30,41 @@ import org.apache.shiro.util.StringUtils * * @since 1.0 */ -public abstract class DomainPermission extends WildcardPermission { +public class DomainPermission extends WildcardPermission { private String domain; - private String actions; - private String targets; + private Set<String> actions; + private Set<String> targets; + + private static final long serialVersionUID = 1l; /** * Creates a domain permission with *all* actions for *all* targets; */ public DomainPermission() { - setParts(getDomain(getClass()), null, null); + this.domain = getDomain(getClass()); + setParts(getDomain(getClass())); } public DomainPermission(String actions) { - setParts(getDomain(getClass()), actions, null); + domain = getDomain(getClass()); + this.actions = StringUtils.splitToSet(actions, SUBPART_DIVIDER_TOKEN); + encodeParts(domain, actions, null); } public DomainPermission(String actions, String targets) { - setParts(getDomain(getClass()), actions, targets); + this.domain = getDomain(getClass()); + this.actions = StringUtils.splitToSet(actions, SUBPART_DIVIDER_TOKEN); + this.targets = StringUtils.splitToSet(actions, SUBPART_DIVIDER_TOKEN); + encodeParts(this.domain, actions, targets); + } + + protected DomainPermission(Set<String> actions, Set<String> targets) { + this.domain = getDomain(getClass()); + setParts(domain, actions, targets); } - protected void setParts(String domain, String actions, String targets) { + private void encodeParts(String domain, String actions, String targets) { if (!StringUtils.hasText(domain)) { throw new IllegalArgumentException("domain argument cannot be null or empty."); } @@ -62,12 +77,21 @@ public abstract class DomainPermission e } else { sb.append(PART_DIVIDER_TOKEN).append(actions); } - if (targets != null) { + if (StringUtils.hasText(targets)) { sb.append(PART_DIVIDER_TOKEN).append(targets); } setParts(sb.toString()); } + protected void setParts(String domain, Set<String> actions, Set<String> targets) { + String actionsString = StringUtils.toDelimitedString(actions, SUBPART_DIVIDER_TOKEN); + String targetsString = StringUtils.toDelimitedString(targets, SUBPART_DIVIDER_TOKEN); + encodeParts(domain, actionsString, targetsString); + this.domain = domain; + this.actions = actions; + this.targets = targets; + } + protected String getDomain(Class<? extends DomainPermission> clazz) { String domain = clazz.getSimpleName().toLowerCase(); //strip any trailing 'permission' text from the name (as all subclasses should have been named): @@ -83,22 +107,35 @@ public abstract class DomainPermission e } protected void setDomain(String domain) { + if (this.domain != null && this.domain.equals(domain)) { + return; + } this.domain = domain; + setParts(domain, actions, targets); } - public String getActions() { + public Set<String> getActions() { return actions; } - protected void setActions(String actions) { + protected void setActions(Set<String> actions) { + if (this.actions != null && this.actions.equals(actions)) { + return; + } this.actions = actions; + setParts(domain, actions, targets); } - public String getTargets() { + public Set<String> getTargets() { return targets; } - protected void setTargets(String targets) { + protected void setTargets(Set<String> targets) { + this.targets = targets; + if (this.targets != null && this.targets.equals(targets)) { + return; + } this.targets = targets; + setParts(domain, actions, targets); } } Modified: shiro/trunk/core/src/main/java/org/apache/shiro/util/StringUtils.java URL: http://svn.apache.org/viewvc/shiro/trunk/core/src/main/java/org/apache/shiro/util/StringUtils.java?rev=1139115&r1=1139114&r2=1139115&view=diff ============================================================================== --- shiro/trunk/core/src/main/java/org/apache/shiro/util/StringUtils.java (original) +++ shiro/trunk/core/src/main/java/org/apache/shiro/util/StringUtils.java Thu Jun 23 23:14:01 2011 @@ -19,14 +19,11 @@ package org.apache.shiro.util; import java.text.ParseException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.StringTokenizer; +import java.util.*; /** * <p>Simple utility class for String operations useful across the framework. - * + * <p/> * <p>Some methods in this class were copied from the Spring Framework so we didn't have to re-invent the wheel, * and in these cases, we have retained all license, copyright and author information. * @@ -36,13 +33,19 @@ public class StringUtils { //TODO - complete JavaDoc - /** Constant representing the empty string, equal to &quot;&quot; */ + /** + * Constant representing the empty string, equal to &quot;&quot; + */ public static final String EMPTY_STRING = ""; - /** Constant representing the default delimiter character (comma), equal to <code>','</code> */ + /** + * Constant representing the default delimiter character (comma), equal to <code>','</code> + */ public static final char DEFAULT_DELIMITER_CHAR = ','; - /** Constant representing the default quote character (double quote), equal to '&quot;'</code> */ + /** + * Constant representing the default quote character (double quote), equal to '&quot;'</code> + */ public static final char DEFAULT_QUOTE_CHAR = '"'; /** @@ -55,7 +58,7 @@ public class StringUtils { * StringUtils.hasText(" ") == false<br/> * StringUtils.hasText("12345") == true<br/> * StringUtils.hasText(" 12345 ") == true</code> - * + * <p/> * <p>Copied from the Spring Framework while retaining all license, copyright and author information. * * @param str the String to check (may be <code>null</code>) @@ -99,7 +102,7 @@ public class StringUtils { /** * Test if the given String starts with the specified prefix, * ignoring upper/lower case. - * + * <p/> * <p>Copied from the Spring Framework while retaining all license, copyright and author information. * * @param str the String to check @@ -124,14 +127,14 @@ public class StringUtils { /** * Returns a 'cleaned' representation of the specified argument. 'Cleaned' is defined as the following: - * + * <p/> * <ol> * <li>If the specified <code>String</code> is <code>null</code>, return <code>null</code></li> * <li>If not <code>null</code>, {@link String#trim() trim()} it.</li> * <li>If the trimmed string is equal to the empty String (i.e. &quot;&quot;), return <code>null</code></li> * <li>If the trimmed string is not the empty string, return the trimmed version</li>. * </ol> - * + * <p/> * Therefore this method always ensures that any given string has trimmed text, and if it doesn't, <code>null</code> * is returned. * @@ -153,30 +156,31 @@ public class StringUtils { /** * Returns the specified array as a comma-delimited (',') string. + * * @param array the array whose contents will be converted to a string. * @return the array's contents as a comma-delimited (',') string. * @since 1.0 */ public static String toString(Object[] array) { - return toDelimitedString(array,","); + return toDelimitedString(array, ","); } /** * Returns the array's contents as a string, with each element delimited by the specified * {@code delimiter} argument. Useful for {@code toString()} implementations and log messages. * - * @param array the array whose contents will be converted to a string + * @param array the array whose contents will be converted to a string * @param delimiter the delimiter to use between each element * @return a single string, delimited by the specified {@code delimiter}. * @since 1.0 */ - public static String toDelimitedString(Object[] array, String delimiter ) { - if ( array == null || array.length == 0 ) { + public static String toDelimitedString(Object[] array, String delimiter) { + if (array == null || array.length == 0) { return EMPTY_STRING; } StringBuilder sb = new StringBuilder(); - for( int i=0; i < array.length; i++ ) { - if ( i > 0 ) { + for (int i = 0; i < array.length; i++) { + if (i > 0) { sb.append(delimiter); } sb.append(array[i]); @@ -185,13 +189,29 @@ public class StringUtils { } /** + * Returns the collection's contents as a string, with each element delimited by the specified + * {@code delimiter} argument. Useful for {@code toString()} implementations and log messages. + * + * @param c the collection whose contents will be converted to a string + * @param delimiter the delimiter to use between each element + * @return a single string, delimited by the specified {@code delimiter}. + * @since 1.2 + */ + public static String toDelimitedString(Collection c, String delimiter) { + if (c == null || c.isEmpty()) { + return EMPTY_STRING; + } + return join(c.iterator(), delimiter); + } + + /** * Tokenize the given String into a String array via a StringTokenizer. * Trims tokens and omits empty tokens. * <p>The given delimiters string is supposed to consist of any number of * delimiter characters. Each of those characters can be used to separate * tokens. A delimiter is always a single character; for multi-character * delimiters, consider using <code>delimitedListToStringArray</code> - * + * <p/> * <p>Copied from the Spring Framework while retaining all license, copyright and author information. * * @param str the String to tokenize @@ -211,7 +231,7 @@ public class StringUtils { * delimiter characters. Each of those characters can be used to separate * tokens. A delimiter is always a single character; for multi-character * delimiters, consider using <code>delimitedListToStringArray</code> - * + * <p/> * <p>Copied from the Spring Framework while retaining all license, copyright and author information. * * @param str the String to tokenize @@ -250,7 +270,7 @@ public class StringUtils { /** * Copy the given Collection into a String array. * The Collection must contain String elements only. - * + * <p/> * <p>Copied from the Spring Framework while retaining all license, copyright and author information. * * @param collection the Collection to copy @@ -321,13 +341,13 @@ public class StringUtils { /** * Splits the specified delimited String into tokens, supporting quoted tokens so that quoted strings themselves * won't be tokenized. - * - * <p>This method's implementation is very loosely based (with significant modifications) on + * <p/> + * This method's implementation is very loosely based (with significant modifications) on * <a href="http://blogs.bytecode.com.au/glen">Glen Smith</a>'s open-source * <a href="http://opencsv.svn.sourceforge.net/viewvc/opencsv/trunk/src/au/com/bytecode/opencsv/CSVReader.java?&view=markup">CSVReader.java</a> * file. - * - * <p>That file is Apache 2.0 licensed as well, making Glen's code a great starting point for us to modify to + * <p/> + * That file is Apache 2.0 licensed as well, making Glen's code a great starting point for us to modify to * our needs. * * @param aLine the String to parse @@ -392,4 +412,70 @@ public class StringUtils { return tokens.toArray(new String[tokens.size()]); } + /** + * Joins the elements of the provided {@code Iterator} into + * a single String containing the provided elements.</p> + * <p/> + * No delimiter is added before or after the list. + * A {@code null} separator is the same as an empty String ("").</p> + * <p/> + * Copied from Commons Lang, version 3 (r1138702).</p> + * + * @param iterator the {@code Iterator} of values to join together, may be null + * @param separator the separator character to use, null treated as "" + * @return the joined String, {@code null} if null iterator input + * @since 1.2 + */ + public static String join(Iterator<?> iterator, String separator) { + final String empty = ""; + + // handle null, zero and one elements before building a buffer + if (iterator == null) { + return null; + } + if (!iterator.hasNext()) { + return empty; + } + Object first = iterator.next(); + if (!iterator.hasNext()) { + return first == null ? empty : first.toString(); + } + + // two or more elements + StringBuilder buf = new StringBuilder(256); // Java default is 16, probably too small + if (first != null) { + buf.append(first); + } + + while (iterator.hasNext()) { + if (separator != null) { + buf.append(separator); + } + Object obj = iterator.next(); + if (obj != null) { + buf.append(obj); + } + } + return buf.toString(); + } + + /** + * Splits the {@code delimited} string (delimited by the specified {@code separator} character) and returns the + * delimited values as a {@code Set}. + * <p/> + * If either argument is {@code null}, this method returns {@code null}. + * + * @param delimited the string to split + * @param separator the character that delineates individual tokens to split + * @return the delimited values as a {@code Set}. + * @since 1.2 + */ + public static Set<String> splitToSet(String delimited, String separator) { + if (delimited == null || separator == null) { + return null; + } + String[] split = split(delimited, separator.charAt(0)); + return CollectionUtils.asSet(split); + } + } From melissadiaz@example.net Sun Jun 26 15:10:30 2011 Return-Path: <melissadiaz@example.net> X-Original-To: melissadiaz@example.net Delivered-To: melissadiaz@example.net Received: from mail.apache.org (hermes.apache.org [83.161.120.155]) by minotaur.apache.org (Postfix) with SMTP id BCF426B89 for <melissadiaz@example.net>; Sun, 26 Jun 2011 15:10:30 +0000 (UTC) Received: (qmail 1157 invoked by uid 500); 26 Jun 2011 15:10:30 -0000 Delivered-To: melissadiaz@example.net Received: (qmail 1126 invoked by uid 500); 26 Jun 2011 15:10:30 -0000 Mailing-List: contact melissadiaz@example.net; run by ezmlm Precedence: bulk List-Help: <mailto:melissadiaz@example.net> List-Unsubscribe: <mailto:melissadiaz@example.net> List-Post: <mailto:melissadiaz@example.net> List-Id: <commits.shiro.apache.org> Reply-To: melissadiaz@example.net Delivered-To: mailing list melissadiaz@example.net Received: (qmail 1119 invoked by uid 99); 26 Jun 2011 15:10:29 -0000 Received: from nike.apache.org (HELO nike.apache.org) (83.161.120.155) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 26 Jun 2011 15:10:29 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [83.161.120.155] (HELO eris.apache.org) (83.161.120.155) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 26 Jun 2011 15:10:27 +0000 Received: from eris.apache.org (localhost [83.161.120.155]) by eris.apache.org (Postfix) with ESMTP id 9F24D238896F for <melissadiaz@example.net>; Sun, 26 Jun 2011 15:10:06 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1139807 - /shiro/sandbox/per-filter-urls/ Date: Sun, 26 Jun 2011 15:10:06 -0000 To: melissadiaz@example.net From: melissadiaz@example.net X-Mailer: svnmailer-1.0.8 Message-Id: <melissadiaz@example.net> X-Virus-Checked: Checked by ClamAV on apache.org Author: adc Date: Sun Jun 26 15:10:06 2011 New Revision: 1139807 URL: http://svn.apache.org/viewvc?rev=1139807&view=rev Log: SHIRO-309 initial review branch Added: shiro/sandbox/per-filter-urls/ - copied from r1139806, shiro/trunk/ From melissadiaz@example.net Sun Jun 26 22:56:00 2011 Return-Path: <melissadiaz@example.net> X-Original-To: melissadiaz@example.net Delivered-To: melissadiaz@example.net Received: from mail.apache.org (hermes.apache.org [83.161.120.155]) by minotaur.apache.org (Postfix) with SMTP id 277436C8A for <melissadiaz@example.net>; Sun, 26 Jun 2011 22:56:00 +0000 (UTC) Received: (qmail 76390 invoked by uid 500); 26 Jun 2011 22:56:00 -0000 Delivered-To: melissadiaz@example.net Received: (qmail 76362 invoked by uid 500); 26 Jun 2011 22:55:59 -0000 Mailing-List: contact melissadiaz@example.net; run by ezmlm Precedence: bulk List-Help: <mailto:melissadiaz@example.net> List-Unsubscribe: <mailto:melissadiaz@example.net> List-Post: <mailto:melissadiaz@example.net> List-Id: <commits.shiro.apache.org> Reply-To: melissadiaz@example.net Delivered-To: mailing list melissadiaz@example.net Received: (qmail 76355 invoked by uid 99); 26 Jun 2011 22:55:59 -0000 Received: from athena.apache.org (HELO athena.apache.org) (83.161.120.155) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 26 Jun 2011 22:55:59 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [83.161.120.155] (HELO eris.apache.org) (83.161.120.155) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 26 Jun 2011 22:55:54 +0000 Received: from eris.apache.org (localhost [83.161.120.155]) by eris.apache.org (Postfix) with ESMTP id 3EA632388906 for <melissadiaz@example.net>; Sun, 26 Jun 2011 22:55:33 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1139964 - /shiro/trunk/tools/hasher/src/main/java/org/apache/shiro/tools/hasher/Hasher.java Date: Sun, 26 Jun 2011 22:55:33 -0000 To: melissadiaz@example.net From: melissadiaz@example.net X-Mailer: svnmailer-1.0.8 Message-Id: <melissadiaz@example.net> Author: lhazlewood Date: Sun Jun 26 22:55:32 2011 New Revision: 1139964 URL: http://svn.apache.org/viewvc?rev=1139964&view=rev Log: SHIRO-279: Minor alterations. Needs to be updated to support a Modular Crypt Format (http://packages.python.org/passlib/modular_crypt_format.html, http://docstore.mik.ua/orelly/other/puis3rd/0596003234_puis3-chp-4-sect-3.html) Modified: shiro/trunk/tools/hasher/src/main/java/org/apache/shiro/tools/hasher/Hasher.java 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=1139964&r1=1139963&r2=1139964&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 Sun Jun 26 22:55:32 2011 @@ -53,7 +53,7 @@ public final class Hasher { 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 PASSWORD = new Option("p", "password", false, "hash a password (disable typing echo)"); - private static final Option PASSWORD_NC = new Option("pnc", "pnoconfirm", false, "disable password hash confirmation prompt."); + 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."); @@ -68,6 +68,13 @@ public final class Hasher { private static final int DEFAULT_NUM_ITERATIONS = 1; private static final String SALT_MUTEX_MSG = createMutexMessage(SALT, SALT_BYTES); + static { + ALGORITHM.setArgName("name"); + SALT_GEN_SIZE.setArgName("numBits"); + ITERATIONS.setArgName("num"); + SALT.setArgName("sval"); + SALT_BYTES.setArgName("encTxt"); + } public static void main(String[] args) { @@ -122,6 +129,7 @@ public final class Hasher { resource = true; } if (line.hasOption(PASSWORD_NC.getOpt())) { + password = true; passwordConfirm = false; } if (line.hasOption(SALT.getOpt())) { @@ -469,12 +477,4 @@ public final class Hasher { } return StringUtils.toDelimitedString(strings, " "); } - - static { - ALGORITHM.setArgName("name"); - SALT_GEN_SIZE.setArgName("numBits"); - ITERATIONS.setArgName("num"); - SALT.setArgName("sval"); - SALT_BYTES.setArgName("encTxt"); - } } From melissadiaz@example.net Sun Jun 26 23:22:16 2011 Return-Path: <melissadiaz@example.net> X-Original-To: melissadiaz@example.net Delivered-To: melissadiaz@example.net Received: from mail.apache.org (hermes.apache.org [83.161.120.155]) by minotaur.apache.org (Postfix) with SMTP id 24B156CC3 for <melissadiaz@example.net>; Sun, 26 Jun 2011 23:22:16 +0000 (UTC) Received: (qmail 2265 invoked by uid 500); 26 Jun 2011 23:22:16 -0000 Delivered-To: melissadiaz@example.net Received: (qmail 2237 invoked by uid 500); 26 Jun 2011 23:22:15 -0000 Mailing-List: contact melissadiaz@example.net; run by ezmlm Precedence: bulk List-Help: <mailto:melissadiaz@example.net> List-Unsubscribe: <mailto:melissadiaz@example.net> List-Post: <mailto:melissadiaz@example.net> List-Id: <commits.shiro.apache.org> Reply-To: melissadiaz@example.net Delivered-To: mailing list melissadiaz@example.net Received: (qmail 2230 invoked by uid 99); 26 Jun 2011 23:22:15 -0000 Received: from nike.apache.org (HELO nike.apache.org) (83.161.120.155) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 26 Jun 2011 23:22:15 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [83.161.120.155] (HELO eris.apache.org) (83.161.120.155) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 26 Jun 2011 23:22:07 +0000 Received: from eris.apache.org (localhost [83.161.120.155]) by eris.apache.org (Postfix) with ESMTP id E29292388897 for <melissadiaz@example.net>; Sun, 26 Jun 2011 23:21:44 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1139968 - in /shiro/trunk: ./ core/src/main/java/org/apache/shiro/mgt/ core/src/test/groovy/org/apache/shiro/mgt/ Date: Sun, 26 Jun 2011 23:21:44 -0000 To: melissadiaz@example.net From: melissadiaz@example.net X-Mailer: svnmailer-1.0.8 Message-Id: <melissadiaz@example.net> X-Virus-Checked: Checked by ClamAV on apache.org Author: lhazlewood Date: Sun Jun 26 23:21:44 2011 New Revision: 1139968 URL: http://svn.apache.org/viewvc?rev=1139968&view=rev Log: SHIRO-266: initial implementation complete. Introduced new concepts (all in the org.apache.shiro.mgt package): - SubjectDAO interface and default DefaultSubjectDAO implementation. - The DefaultSubjectDAO implementation uses a SessionStateEvaluator (an interface) that allows control of session usage on a per-subject basis. - The DefaultSessionStateEvaluator allows session control for all Subjects at a global level. Custom per-session logic may be performed by end-users implementing the SessionStateEvaluator interface and configuring it on the SessionDAO. No subclassing of an existing Shiro implementation required. - The DefaultSubjectDAO implementation uses efficient 'merge' logic for persisting data to the session - a session is only ever updated if there is a difference in subject state. Added: shiro/trunk/core/src/main/java/org/apache/shiro/mgt/DefaultSessionStorageEvaluator.java shiro/trunk/core/src/main/java/org/apache/shiro/mgt/DefaultSubjectDAO.java shiro/trunk/core/src/main/java/org/apache/shiro/mgt/SessionStorageEvaluator.java shiro/trunk/core/src/main/java/org/apache/shiro/mgt/SubjectDAO.java shiro/trunk/core/src/test/groovy/org/apache/shiro/mgt/ shiro/trunk/core/src/test/groovy/org/apache/shiro/mgt/DefaultSubjectDAOTest.groovy Modified: shiro/trunk/RELEASE-NOTES shiro/trunk/core/src/main/java/org/apache/shiro/mgt/DefaultSecurityManager.java Modified: shiro/trunk/RELEASE-NOTES URL: http://svn.apache.org/viewvc/shiro/trunk/RELEASE-NOTES?rev=1139968&r1=1139967&r2=1139968&view=diff ============================================================================== --- shiro/trunk/RELEASE-NOTES (original) +++ shiro/trunk/RELEASE-NOTES Sun Jun 26 23:21:44 2011 @@ -21,20 +21,20 @@ combined with Jira's auto-generated rele total set. ########################################################### -# 1.1.0 +# 1.2.0 ########################################################### Backwards Incompatible Changes -------------------------------- -- The org.apache.shiro.web.util.RedirectView class's - appendQueryProperties(StringBuffer targetUrl, Map model, String encodingScheme) - method has been changed to accept a StringBuilder argument instead of a - StringBuffer per SHIRO-191. RedirectView is considered an internal - implementation support class and Shiro end-users should not be affected by this. +- The following org.apache.shiro.mgt.DefaultSecurityManager methods have been removed: + bindPrincipalsToSession(principals, context) -########################################################### -# 1.2.0 -########################################################### + This logic has been moved into a SubjectDAO concept to allow end-users to control + exactly how the Session may be used for subject state persistence. This allows a + single point of control rather than needing to configure Shiro in multiple places. + + If you overrode this method in Shiro 1.0 or 1.2, please look at the new + org.apache.shiro.mgt.DefaultSubjectDAO implementation, which performs compatible logic. Potential Breaking Changes -------------------------------- @@ -44,6 +44,14 @@ Potential Breaking Changes If you ever called this method, you can call the addFilter(name, filter, true) method to achieve the <= 1.1 behavior. +########################################################### +# 1.1.0 +########################################################### - - +Backwards Incompatible Changes +-------------------------------- +- The org.apache.shiro.web.util.RedirectView class's + appendQueryProperties(StringBuffer targetUrl, Map model, String encodingScheme) + method has been changed to accept a StringBuilder argument instead of a + StringBuffer per SHIRO-191. RedirectView is considered an internal + implementation support class and Shiro end-users should not be affected by this. Modified: shiro/trunk/core/src/main/java/org/apache/shiro/mgt/DefaultSecurityManager.java URL: http://svn.apache.org/viewvc/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/DefaultSecurityManager.java?rev=1139968&r1=1139967&r2=1139968&view=diff ============================================================================== --- shiro/trunk/core/src/main/java/org/apache/shiro/mgt/DefaultSecurityManager.java (original) +++ shiro/trunk/core/src/main/java/org/apache/shiro/mgt/DefaultSecurityManager.java Sun Jun 26 23:21:44 2011 @@ -70,12 +70,10 @@ import java.util.Collection; */ public class DefaultSecurityManager extends SessionsSecurityManager { - //TODO - complete JavaDoc - private static final Logger log = LoggerFactory.getLogger(DefaultSecurityManager.class); protected RememberMeManager rememberMeManager; - + protected SubjectDAO subjectDAO; protected SubjectFactory subjectFactory; /** @@ -84,6 +82,7 @@ public class DefaultSecurityManager exte public DefaultSecurityManager() { super(); this.subjectFactory = new DefaultSubjectFactory(); + this.subjectDAO = new DefaultSubjectDAO(); } /** @@ -114,6 +113,14 @@ public class DefaultSecurityManager exte this.subjectFactory = subjectFactory; } + public SubjectDAO getSubjectDAO() { + return subjectDAO; + } + + public void setSubjectDAO(SubjectDAO subjectDAO) { + this.subjectDAO = subjectDAO; + } + public RememberMeManager getRememberMeManager() { return rememberMeManager; } @@ -149,53 +156,17 @@ public class DefaultSecurityManager exte /** * Binds a {@code Subject} instance created after authentication to the application for later use. * <p/> - * The default implementation simply stores the Subject's principals and authentication state to the - * {@code Subject}'s {@link Subject#getSession() session} to ensure it is available for reference later. + * As of Shiro 1.2, this method has been deprecated in favor of {@link #save(org.apache.shiro.subject.Subject)}, + * which this implementation now calls. * * @param subject the {@code Subject} instance created after authentication to be bound to the application * for later use. + * @see #save(org.apache.shiro.subject.Subject) + * @deprecated in favor of {@link #save(org.apache.shiro.subject.Subject) save(subject)}. */ + @Deprecated protected void bind(Subject subject) { - // TODO consider refactoring to use Subject.Binder. - // This implementation was copied from SessionSubjectBinder that was removed - PrincipalCollection principals = subject.getPrincipals(); - if (principals != null && !principals.isEmpty()) { - Session session = subject.getSession(); - bindPrincipalsToSession(principals, session); - } else { - Session session = subject.getSession(false); - if (session != null) { - session.removeAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY); - } - } - - if (subject.isAuthenticated()) { - Session session = subject.getSession(); - session.setAttribute(DefaultSubjectContext.AUTHENTICATED_SESSION_KEY, subject.isAuthenticated()); - } else { - Session session = subject.getSession(false); - if (session != null) { - session.removeAttribute(DefaultSubjectContext.AUTHENTICATED_SESSION_KEY); - } - } - } - - /** - * Saves the specified identity to the given session, making the session no longer anonymous. - * - * @param principals the Subject identity to save to the session - * @param session the Session to retain the Subject identity. - * @throws IllegalArgumentException if the principals are null or empty or the session is null - * @since 1.0 - */ - private void bindPrincipalsToSession(PrincipalCollection principals, Session session) throws IllegalArgumentException { - if (session == null) { - throw new IllegalArgumentException("Session argument cannot be null."); - } - if (CollectionUtils.isEmpty(principals)) { - throw new IllegalArgumentException("Principals cannot be null or empty."); - } - session.setAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY, principals); + save(subject); } protected void rememberMeSuccessfulLogin(AuthenticationToken token, AuthenticationInfo info, Subject subject) { @@ -281,9 +252,8 @@ public class DefaultSecurityManager exte Subject loggedIn = createSubject(token, info, subject); - bind(loggedIn); - onSuccessfulLogin(token, info, loggedIn); + return loggedIn; } @@ -304,16 +274,25 @@ public class DefaultSecurityManager exte } /** - * This implementation attempts to resolve any session ID that may exist in the context by - * passing it to the {@link #resolveSession(SubjectContext)} method. The - * return value from that call is then used to attempt to resolve the subject identity via the - * {@link #resolvePrincipals(SubjectContext)} method. The return value from that call is then used to create - * the {@code Subject} instance by calling - * <code>{@link #getSubjectFactory() getSubjectFactory()}.{@link SubjectFactory#createSubject createSubject}(resolvedContext);</code> + * This implementation functions as follows: + * <p/> + * <ol> + * <li>Ensures the {@code SubjectContext} is as populated as it can be, using heuristics to acquire + * data that may not have already been available to it (such as a referenced session or remembered principals).</li> + * <li>Calls {@link #doCreateSubject(org.apache.shiro.subject.SubjectContext)} to actually perform the + * {@code Subject} instance creation.</li> + * <li>calls {@link #save(org.apache.shiro.subject.Subject) save(subject)} to ensure the constructed + * {@code Subject}'s state is accessible for future requests/invocations if necessary.</li> + * <li>returns the constructed {@code Subject} instance.</li> + * </ol> * * @param subjectContext any data needed to direct how the Subject should be constructed. - * @return the {@code Subject} instance reflecting the specified initialization data. - * @see SubjectFactory#createSubject + * @return the {@code Subject} instance reflecting the specified contextual data. + * @see #ensureSecurityManager(org.apache.shiro.subject.SubjectContext) + * @see #resolveSession(org.apache.shiro.subject.SubjectContext) + * @see #resolvePrincipals(org.apache.shiro.subject.SubjectContext) + * @see #doCreateSubject(org.apache.shiro.subject.SubjectContext) + * @see #save(org.apache.shiro.subject.Subject) * @since 1.0 */ public Subject createSubject(SubjectContext subjectContext) { @@ -332,10 +311,63 @@ public class DefaultSecurityManager exte //if possible before handing off to the SubjectFactory: context = resolvePrincipals(context); + Subject subject = doCreateSubject(context); + + //save this subject for future reference if necessary: + //(this is needed here in case rememberMe principals were resolved and they need to be stored in the + //session, so we don't constantly rehydrate the rememberMe PrincipalCollection on every operation). + //Added in 1.2: + save(subject); + + return subject; + } + + /** + * Actually creates a {@code Subject} instance by delegating to the internal + * {@link #getSubjectFactory() subjectFactory}. By the time this method is invoked, all possible + * {@code SubjectContext} data (session, principals, et. al.) has been made accessible using all known heuristics + * and will be accessible to the {@code subjectFactory} via the {@code subjectContext.resolve*} methods. + * + * @param context the populated context (data map) to be used by the {@code SubjectFactory} when creating a + * {@code Subject} instance. + * @return a {@code Subject} instance reflecting the data in the specified {@code SubjectContext} data map. + * @see #getSubjectFactory() + * @see SubjectFactory#createSubject(org.apache.shiro.subject.SubjectContext) + * @since 1.2 + */ + protected Subject doCreateSubject(SubjectContext context) { return getSubjectFactory().createSubject(context); } /** + * Saves the subject's state to a persistent location for future reference if necessary. + * <p/> + * This implementation merely delegates to the internal {@link #setSubjectDAO(SubjectDAO) subjectDAO} and calls + * {@link SubjectDAO#save(org.apache.shiro.subject.Subject) subjectDAO.save(subject)}. + * + * @param subject the subject for which state will potentially be persisted + * @see SubjectDAO#save(org.apache.shiro.subject.Subject) + * @since 1.2 + */ + protected void save(Subject subject) { + this.subjectDAO.save(subject); + } + + /** + * Removes (or 'unbinds') the Subject's state from the application, typically called during {@link #logout}.. + * <p/> + * This implementation merely delegates to the internal {@link #setSubjectDAO(SubjectDAO) subjectDAO} and calls + * {@link SubjectDAO#delete(org.apache.shiro.subject.Subject) delete(subject)}. + * + * @param subject the subject for which state will be removed + * @see SubjectDAO#delete(org.apache.shiro.subject.Subject) + * @since 1.2 + */ + protected void delete(Subject subject) { + this.subjectDAO.delete(subject); + } + + /** * Determines if there is a {@code SecurityManager} instance in the context, and if not, adds 'this' to the * context. This ensures the SubjectFactory instance will have access to a SecurityManager during Subject * construction if necessary. @@ -362,7 +394,7 @@ public class DefaultSecurityManager exte * <p/> * If there is a {@code Session} already in the context because that is what the caller wants to be used for * {@code Subject} construction, or if no session is resolved, this method effectively does nothing - * returns the Map method argument unaltered. + * returns the context method argument unaltered. * * @param context the subject context data that may resolve a Session instance. * @return The context to use to pass to a {@link SubjectFactory} for subject creation. @@ -405,15 +437,13 @@ public class DefaultSecurityManager exte } /** - * Attempts to resolve an identity (a {@link PrincipalCollection}) for the context using heuristics. The - * implementation strategy: + * Attempts to resolve an identity (a {@link PrincipalCollection}) for the context using heuristics. This + * implementation functions as follows: * <ol> * <li>Check the context to see if it can already {@link SubjectContext#resolvePrincipals resolve an identity}. If * so, this method does nothing and returns the method argument unaltered.</li> * <li>Check for a RememberMe identity by calling {@link #getRememberedIdentity}. If that method returns a * non-null value, place the remembered {@link PrincipalCollection} in the context.</li> - * <li>If the remembered identity is discovered, associate it with the session to eliminate unnecessary - * rememberMe accesses for the remainder of the session</li> * </ol> * * @param context the subject context data that may provide (directly or indirectly through one of its values) a @@ -436,7 +466,22 @@ public class DefaultSecurityManager exte "for subject construction by the SubjectFactory."); context.setPrincipals(principals); - bindPrincipalsToSession(principals, context); + + // The following call was removed (commented out) in Shiro 1.2 because it uses the session as an + // implementation strategy. Session use for Shiro's own needs should be controlled in a single place + // to be more manageable
{'source': 'Apache Software Foundation Public Mail Archives'}