Repository: shiro Updated Branches: refs/heads/master 1460419cc -> 64d9f8341
Force RememberMe cipher to be set to survive JVM restart. If the property is not set, a new cipher will be generated. Project: http://git-wip-us.apache.org/repos/asf/shiro/repo Commit: http://git-wip-us.apache.org/repos/asf/shiro/commit/64d9f834 Tree: http://git-wip-us.apache.org/repos/asf/shiro/tree/64d9f834 Diff: http://git-wip-us.apache.org/repos/asf/shiro/diff/64d9f834 Branch: refs/heads/master Commit: 64d9f8341e1aa7ef1a29744e16ea7c578ca5deee Parents: 1460419 Author: bdemers <[email protected]> Authored: Fri May 6 16:22:45 2016 -0400 Committer: bdemers <[email protected]> Committed: Fri May 6 16:22:45 2016 -0400 ---------------------------------------------------------------------- .../shiro/mgt/AbstractRememberMeManager.java | 16 ++------ .../samples/guice/SampleShiroServletModule.java | 29 ++++++++++++++ samples/guice/src/main/webapp/WEB-INF/shiro.ini | 4 ++ samples/web/src/main/webapp/WEB-INF/shiro.ini | 4 ++ .../web/mgt/CookieRememberMeManagerTest.java | 40 ++++++++++++++++++++ 5 files changed, 80 insertions(+), 13 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/shiro/blob/64d9f834/core/src/main/java/org/apache/shiro/mgt/AbstractRememberMeManager.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/shiro/mgt/AbstractRememberMeManager.java b/core/src/main/java/org/apache/shiro/mgt/AbstractRememberMeManager.java index 0b1df0a..c857ef9 100644 --- a/core/src/main/java/org/apache/shiro/mgt/AbstractRememberMeManager.java +++ b/core/src/main/java/org/apache/shiro/mgt/AbstractRememberMeManager.java @@ -69,17 +69,6 @@ public abstract class AbstractRememberMeManager implements RememberMeManager { private static final Logger log = LoggerFactory.getLogger(AbstractRememberMeManager.class); /** - * The following Base64 string was generated by auto-generating an AES Key: - * <pre> - * AesCipherService aes = new AesCipherService(); - * byte[] key = aes.generateNewKey().getEncoded(); - * String base64 = Base64.encodeToString(key); - * </pre> - * The value of 'base64' was copied-n-pasted here: - */ - private static final byte[] DEFAULT_CIPHER_KEY_BYTES = Base64.decode("kPH+bIxk5D2deZiIxcaaaA=="); - - /** * Serializer to use for converting PrincipalCollection instances to/from byte arrays */ private Serializer<PrincipalCollection> serializer; @@ -105,8 +94,9 @@ public abstract class AbstractRememberMeManager implements RememberMeManager { */ public AbstractRememberMeManager() { this.serializer = new DefaultSerializer<PrincipalCollection>(); - this.cipherService = new AesCipherService(); - setCipherKey(DEFAULT_CIPHER_KEY_BYTES); + AesCipherService cipherService = new AesCipherService(); + this.cipherService = cipherService; + setCipherKey(cipherService.generateNewKey().getEncoded()); } /** http://git-wip-us.apache.org/repos/asf/shiro/blob/64d9f834/samples/guice/src/main/java/org/apache/shiro/samples/guice/SampleShiroServletModule.java ---------------------------------------------------------------------- diff --git a/samples/guice/src/main/java/org/apache/shiro/samples/guice/SampleShiroServletModule.java b/samples/guice/src/main/java/org/apache/shiro/samples/guice/SampleShiroServletModule.java index e5575be..01a0113 100644 --- a/samples/guice/src/main/java/org/apache/shiro/samples/guice/SampleShiroServletModule.java +++ b/samples/guice/src/main/java/org/apache/shiro/samples/guice/SampleShiroServletModule.java @@ -19,10 +19,16 @@ package org.apache.shiro.samples.guice; import com.google.inject.Provides; +import com.google.inject.binder.AnnotatedBindingBuilder; import com.google.inject.name.Names; +import org.apache.shiro.codec.Base64; +import org.apache.shiro.config.ConfigurationException; import org.apache.shiro.config.Ini; import org.apache.shiro.guice.web.ShiroWebModule; import org.apache.shiro.realm.text.IniRealm; +import org.apache.shiro.web.mgt.CookieRememberMeManager; +import org.apache.shiro.web.mgt.DefaultWebSecurityManager; +import org.apache.shiro.web.mgt.WebSecurityManager; import javax.inject.Singleton; import javax.servlet.ServletContext; @@ -59,4 +65,27 @@ public class SampleShiroServletModule extends ShiroWebModule { URL iniUrl = servletContext.getResource("/WEB-INF/shiro.ini"); return Ini.fromResourcePath("url:" + iniUrl.toExternalForm()); } + + @Override + protected void bindWebSecurityManager(AnnotatedBindingBuilder<? super WebSecurityManager> bind) + { + try + { + String cipherKey = loadShiroIni().getSectionProperty( "main", "securityManager.rememberMeManager.cipherKey" ); + + DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); + CookieRememberMeManager rememberMeManager = new CookieRememberMeManager(); + rememberMeManager.setCipherKey( Base64.decode( cipherKey ) ); + securityManager.setRememberMeManager(rememberMeManager); + bind.toInstance(securityManager); + } + catch ( MalformedURLException e ) + { + // for now just throw, you could just call + // super.bindWebSecurityManager(bind) if you do not need rememberMe functionality + throw new ConfigurationException( "securityManager.rememberMeManager.cipherKey must be set in shiro.ini." ); + } + + + } } http://git-wip-us.apache.org/repos/asf/shiro/blob/64d9f834/samples/guice/src/main/webapp/WEB-INF/shiro.ini ---------------------------------------------------------------------- diff --git a/samples/guice/src/main/webapp/WEB-INF/shiro.ini b/samples/guice/src/main/webapp/WEB-INF/shiro.ini index 4ce1f71..10dec1d 100644 --- a/samples/guice/src/main/webapp/WEB-INF/shiro.ini +++ b/samples/guice/src/main/webapp/WEB-INF/shiro.ini @@ -24,6 +24,10 @@ [main] shiro.loginUrl = /login.jsp +# we need to set the cipherKey, so the rememberMe cookie +# will work after restarting the web app +securityManager.rememberMeManager.cipherKey = kPH+bIxk5D2deZiIxcaaaA== + [users] # format: username = password, role1, role2, ..., roleN root = secret,admin http://git-wip-us.apache.org/repos/asf/shiro/blob/64d9f834/samples/web/src/main/webapp/WEB-INF/shiro.ini ---------------------------------------------------------------------- diff --git a/samples/web/src/main/webapp/WEB-INF/shiro.ini b/samples/web/src/main/webapp/WEB-INF/shiro.ini index 7051bf8..c06ec68 100644 --- a/samples/web/src/main/webapp/WEB-INF/shiro.ini +++ b/samples/web/src/main/webapp/WEB-INF/shiro.ini @@ -23,6 +23,10 @@ [main] listener = org.apache.shiro.config.event.LoggingBeanEventListener +# we need to set the cipherKey, so the rememberMe cookie +# will work after restarting the web app +securityManager.rememberMeManager.cipherKey = kPH+bIxk5D2deZiIxcaaaA== + shiro.loginUrl = /login.jsp [users] http://git-wip-us.apache.org/repos/asf/shiro/blob/64d9f834/web/src/test/java/org/apache/shiro/web/mgt/CookieRememberMeManagerTest.java ---------------------------------------------------------------------- diff --git a/web/src/test/java/org/apache/shiro/web/mgt/CookieRememberMeManagerTest.java b/web/src/test/java/org/apache/shiro/web/mgt/CookieRememberMeManagerTest.java index 1144575..2f07865 100644 --- a/web/src/test/java/org/apache/shiro/web/mgt/CookieRememberMeManagerTest.java +++ b/web/src/test/java/org/apache/shiro/web/mgt/CookieRememberMeManagerTest.java @@ -18,9 +18,12 @@ */ package org.apache.shiro.web.mgt; +import com.sun.org.apache.xerces.internal.impl.dv.util.Base64; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.SimpleAuthenticationInfo; import org.apache.shiro.authc.UsernamePasswordToken; +import org.apache.shiro.crypto.AesCipherService; +import org.apache.shiro.crypto.CipherService; import org.apache.shiro.crypto.CryptoException; import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.web.servlet.ShiroHttpServletRequest; @@ -138,6 +141,7 @@ public class CookieRememberMeManagerTest { replay(mockRequest); CookieRememberMeManager mgr = new CookieRememberMeManager(); + mgr.setCipherKey( Base64.decode("kPH+bIxk5D2deZiIxcaaaA==")); PrincipalCollection collection = mgr.getRememberedPrincipals(context); verify(mockRequest); @@ -147,6 +151,42 @@ public class CookieRememberMeManagerTest { assertTrue(collection.iterator().next().equals("user")); } + @Test(expected = CryptoException.class) + public void getRememberedPrincipalsNoMoreDefaultCipher() { + HttpServletRequest mockRequest = createMock(HttpServletRequest.class); + HttpServletResponse mockResponse = createMock(HttpServletResponse.class); + WebSubjectContext context = new DefaultWebSubjectContext(); + context.setServletRequest(mockRequest); + context.setServletResponse(mockResponse); + + expect(mockRequest.getAttribute(ShiroHttpServletRequest.IDENTITY_REMOVED_KEY)).andReturn(null); + expect(mockRequest.getContextPath()).andReturn( "/test" ); + + + //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 = "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) + }; + + expect(mockRequest.getCookies()).andReturn(cookies); + replay(mockRequest); + + CookieRememberMeManager mgr = new CookieRememberMeManager(); + // without the old default cipher set, this will fail (expected) + // mgr.setCipherKey( Base64.decode("kPH+bIxk5D2deZiIxcaaaA==")); + // this will throw a CryptoException + mgr.getRememberedPrincipals(context); + } + // SHIRO-69 @Test
