Les,

Thanks, this works perfectly. Note that I had to use encodeToString()
instead of encode():

int keySize = 128;
String key = Base64.encodeToString(new
AesCipherService().generateNewKey(keySize).getEncoded());

I'll just ignore the exceptions in the logs, as they will eventually go away
when everyone has a new cookie.

Tauren



On Wed, May 12, 2010 at 1:51 PM, Les Hazlewood <[email protected]>wrote:

> Hi Tauren,
>
> The easiest way is to probably use the MethodInvokingFactoryBean for this:
>
> <bean id="myRememberMeManager" class="...">
>    <property name="cipherKey" ref="cipherKeyBytes"/>
> </bean>
>
> <bean id="cipherKeyBytes"
> class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
>   <property name="targetClass" value="org.apache.shiro.codec.Base64"/>
>   <property name="targetMethod" value="decode"/>
>   <property name="arguments">
>     <list>
>       <value>your_base64_encoded_string</value>
>     </list>
>   </property>
> </bean>
>
> Cheers,
>
> Les
>
> On Wed, May 12, 2010 at 12:58 PM, Tauren Mills <[email protected]> wrote:
> > Les,
> > Thanks, this is helpful. I'd like to use my own custom cipherKey, but I'm
> > not using INI configuration. Could you perhaps explain how to configure
> this
> > using Spring instead of INI? I think this too would be useful information
> to
> > go into the wiki.  Here's my current spring config:
> >   <bean id="securityManager"
> > class="org.apache.shiro.web.DefaultWebSecurityManager">
> >     <property name="realm" ref="myRealm"/>
> >     <property name="rememberMeManager" ref="myRememberMeManager"/>
> >   </bean>
> >   <bean name="myRememberMeManager"
> > class="com.project.security.MyRememberMeManager"/>
> > Thanks!
> > Tauren
> >
> > On Wed, May 12, 2010 at 12:24 PM, Les Hazlewood <[email protected]>
> > wrote:
> >>
> >> Yep, you're exactly right - it is because of the new (more secure)
> >> CipherService instances.  I would ignore these warnings - the
> >> rememberMe cookie will be deleted and a new correct one will be
> >> auto-created the next time they log in (and they click 'remember me'
> >> of course).
> >>
> >> If you didn't want to ignore them and have them just work, you can do 3
> >> things:
> >>
> >> 1.  Configure the RememberMeManager to use the BlowfishCipherService.
> >> Prior to the 1.0 release, we defaulted to using the Blowfish
> >> algorithm, but most people prefer AES, so now we default to the
> >> AesCipherService.
> >> 2.  Ensure that the new BlowfishCipherService is using the _exact_
> >> same key that was used before.  This is simple if you're using your
> >> own cipher key.  It is harder if you were using Shiro's default
> >> blowfish key, at which point you would need to look at the old source
> >> code to find it.
> >> 3.  Ensure that your BlowfishCipherService instance's
> >> 'generateInitializationVectors' attribute is set to false.
> >>
> >> Step 3 makes the encryption less secure and overall 1-3 can be a pain.
> >>  I'd recommend just ignoring the warnings for now and let the new
> >> cookies replace the old ones if you are ok with that.
> >>
> >> One thing you might want to try is using your own cipher key with the
> >> CipherService instance - it makes it more secure instead of using
> >> Shiro's default (which could be discovered by a 3rd party).  To be
> >> fair, the encrypted data is just a serialized PrincipalCollection, so
> >> if you're not storing sensitive data in the PC, you don't really need
> >> to do this.  I still like to do it though in case I ever do need to
> >> use an AES Cipher to encrypt something sensitive - then my key is all
> >> ready to go.
> >>
> >> You can do this by doing the following:
> >>
> >> //AES algorithm only supports key sizes of 128, 192, and 256 bits.
> >> //192 and 256 require that the JCE Unlimited Strength
> >> //Jurisdiction Policy files to be installed.
> >> int keySize = 128;
> >> String key = Base64.encode(new
> >> AesCipherService().generateNewKey(keySize).getEncoded());
> >>
> >> //then you can use this key in your shiro config:
> >>
> >> [main]
> >> securityManager.rememberMeManager.cipherKey =
> >> your_base64_encoded_string_from_above
> >>
> >> The configurator will automatically recognize that is a byte array
> >> property and Base64 decode the string value into the correct bytes.
> >> If you wanted to use Hex encoding instead, make sure you prefix your
> >> encoded string with 0x ('zero' 'x'):
> >>
> >> securityManager.rememberMeManager.cipherKey = 0x123456789ABCDEF
> >>
> >> which will trigger Hex decoding instead.
> >>
> >> I know I've rambled on about this, but hopefully this will be indexed
> >> by Google and help someone else in the future.  It also gives me a
> >> base to use to update the wiki documentation :)
> >>
> >> Cheers,
> >>
> >> Les
> >>
> >> 1.  Ensure that the cipher service is using the same cipher key
> >> you could configure your CipherService to set
> >> 'generateInitializationVectors' to false, in which case the previou
> >>
> >> On Wed, May 12, 2010 at 11:08 AM, Tauren Mills <[email protected]>
> wrote:
> >> > Also, I'm getting the following exception in my logs. I'm assuming
> that
> >> > is
> >> > just because people have old cookies with old cyphers, and that once
> >> > their
> >> > cookies are replaced, I won't see these exceptions anymore. I also
> >> > assume
> >> > this means that everyone is being forced to log in again since my app
> >> > has
> >> > been updated with the latest shiro and that no existing rememberme
> >> > cookies
> >> > will work.  Is this correct?
> >> > Thanks,
> >> > Tauren
> >> > ---
> >> >
> >> > WARN  - DefaultSecurityManager     - Delegate RememberMeManager
> instance
> >> > of
> >> > type [com.project.security.MyRememberMeManager] threw an exception
> >> > during
> >> > getRememberedPrincipals().
> >> > org.apache.shiro.crypto.CryptoException: Unable to execute 'doFinal'
> >> > with
> >> > cipher instance [javax.crypto.cip...@5b3bd1c0].
> >> > at
> >> >
> org.apache.shiro.crypto.JcaCipherService.crypt(JcaCipherService.java:465)
> >> > at
> >> >
> org.apache.shiro.crypto.JcaCipherService.crypt(JcaCipherService.java:448)
> >> > at
> >> >
> >> >
> org.apache.shiro.crypto.JcaCipherService.decrypt(JcaCipherService.java:393)
> >> > at
> >> >
> >> >
> org.apache.shiro.crypto.JcaCipherService.decrypt(JcaCipherService.java:385)
> >> > at
> >> >
> >> >
> org.apache.shiro.mgt.AbstractRememberMeManager.decrypt(AbstractRememberMeManager.java:491)
> >> > at
> >> >
> >> >
> org.apache.shiro.mgt.AbstractRememberMeManager.convertBytesToPrincipals(AbstractRememberMeManager.java:431)
> >> > at
> >> >
> >> >
> org.apache.shiro.mgt.AbstractRememberMeManager.getRememberedPrincipals(AbstractRememberMeManager.java:398)
> >> > at
> >> >
> >> >
> com.project.security.MyRememberMeManager.getRememberedPrincipals(MyRememberMeManager.java:21)
> >> > at
> >> >
> >> >
> org.apache.shiro.mgt.DefaultSecurityManager.getRememberedIdentity(DefaultSecurityManager.java:526)
> >> > at
> >> >
> >> >
> org.apache.shiro.mgt.DefaultSecurityManager.resolvePrincipals(DefaultSecurityManager.java:403)
> >> > at
> >> >
> >> >
> org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:320)
> >> > at
> >> >
> org.apache.shiro.subject.Subject$Builder.buildSubject(Subject.java:767)
> >> > at
> >> >
> >> >
> org.apache.shiro.web.subject.WebSubject$Builder.buildWebSubject(WebSubject.java:101)
> >> > at org.apache.shiro.web.servlet.ShiroFilter.bind(ShiroFilter.java:540)
> >> > at
> >> >
> >> >
> org.apache.shiro.web.servlet.ShiroFilter.doFilterInternal(ShiroFilter.java:627)
> >> > at
> >> >
> >> >
> org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:83)
> >> > at
> >> >
> >> >
> org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1088)
> >> > at
> >> >
> >> >
> org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198)
> >> > at
> >> >
> >> >
> org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
> >> > at
> >> >
> >> >
> org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1088)
> >> > at
> >> >
> org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:360)
> >> > at
> >> >
> >> >
> org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
> >> > at
> >> >
> org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
> >> > at
> >> >
> org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:729)
> >> > at
> org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405)
> >> > at
> >> >
> org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
> >> > at org.mortbay.jetty.Server.handle(Server.java:324)
> >> > at
> >> >
> org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:505)
> >> > at
> >> >
> >> >
> org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:829)
> >> > at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:513)
> >> > at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:211)
> >> > at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:380)
> >> > at
> >> >
> >> >
> org.mortbay.jetty.bio.SocketConnector$Connection.run(SocketConnector.java:228)
> >> > at
> >> >
> >> >
> org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:488)
> >> > Caused by: javax.crypto.BadPaddingException: Given final block not
> >> > properly
> >> > padded
> >> > at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
> >> > at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
> >> > at com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..)
> >> > at javax.crypto.Cipher.doFinal(DashoA13*..)
> >> > at
> >> >
> org.apache.shiro.crypto.JcaCipherService.crypt(JcaCipherService.java:462)
> >> > ... 33 more
> >> >
> >> > On Wed, May 12, 2010 at 9:49 AM, Tauren Mills <[email protected]>
> wrote:
> >> >>
> >> >> Les,
> >> >> Thanks for the help.  However, now I'm having a problem
> >> >> with getRememberedPrincipals() being called dozens of times per page
> >> >> view, causing my "accessed" property to be updated many times, which
> is
> >> >> obviously not ideal.
> >> >> I believe this is because my application is running in Jetty, so
> every
> >> >> image, JS, CSS, and other resource is causing a request to be
> created.
> >> >> My
> >> >> cookie is set to / since I need it to work for many different paths.
> >> >> Any suggestions on how to only update my "accessed" property a single
> >> >> time
> >> >> per session?  I don't need the property updated with every request,
> >> >> just
> >> >> when they first access the site for a session is fine.  Basically,
> the
> >> >> property I currently called "accessed" would actually be more
> >> >> accurately
> >> >> called "lastLogin".
> >> >> Below is code if it helps.
> >> >> Thanks,
> >> >> Tauren
> >> >> ---
> >> >> public class MyRememberMeManager extends CookieRememberMeManager {
> >> >> private MemberService memberService;
> >> >>     @Autowired
> >> >> public void setMemberService(MemberService memberService) {
> >> >> this.memberService = memberService;
> >> >> }
> >> >> @Override
> >> >> public PrincipalCollection getRememberedPrincipals(SubjectContext
> >> >> subjectContext) {
> >> >> PrincipalCollection principals =
> >> >> super.getRememberedPrincipals(subjectContext);
> >> >> if ( principals != null ) {
> >> >> Long id = (Long) principals.getPrimaryPrincipal();
> >> >> memberService.updateAccessed(id);
> >> >> }
> >> >> return principals;
> >> >> }
> >> >> }
> >> >> // MemberServiceImpl.java
> >> >> public void updateAccessed(Long id) {
> >> >> updateAccessed(findById(id));
> >> >> }
> >> >> public void updateAccessed(Member member) {
> >> >> member.setAccessed(new Date());
> >> >> memberDao.save(member);
> >> >> }
> >> >>
> >> >> // Spring config
> >> >>     <bean id="securityManager"
> >> >> class="org.apache.shiro.web.DefaultWebSecurityManager">
> >> >>       property instead. -->
> >> >>         <property name="realm" ref="myRealm"/>
> >> >>         <property name="rememberMeManager"
> ref="myRememberMeManager"/>
> >> >>     </bean>
> >> >>     <bean name="myRememberMeManager"
> >> >> class="com.project.security.MyRememberMeManager"/>
> >> >>
> >> >> On Tue, May 11, 2010 at 10:11 AM, Les Hazlewood <
> [email protected]>
> >> >> wrote:
> >> >>>
> >> >>> Hi Tauren,
> >> >>>
> >> >>> Yes, WebRememberMeManager has been deprecated in favor of the new
> >> >>> CookieRememberMeManager which uses a new Cookie property and not the
> >> >>> (now deprecated) CookieAttribute concept.  CookieAttribute was
> complex
> >> >>> and confusing.  The new Cookie interface and implementation in
> >> >>> comparison are much easier to understand and configure.  So, if you
> >> >>> extend CookieRememberMeManager, you should be closely back to where
> >> >>> you were when you extended WebRememberMeManager.
> >> >>>
> >> >>> As for the SubjectContext - it was added within the last two weeks
> to
> >> >>> satisfy a technical requirement: the (now new)
> SubjectContext.resolve*
> >> >>> method behavior was needed in multiple places across more than one
> OO
> >> >>> hierarchy.  So, we either had to copy-n-paste logic (yuck) or
> >> >>> consolidate it into a component.  The SubjectContext satisfies this
> >> >>> need and will stay in place instead of the raw Map.
> >> >>>
> >> >>> Also note that for 1.0, we'll be removing all Deprecated classes and
> >> >>> methods.  Since we're wrapping up coding issues today (and possibly
> >> >>> tomorrow), we'll be deleting them any time now.
> >> >>>
> >> >>> I hope that helps!
> >> >>>
> >> >>> Les
> >> >>>
> >> >>> On Tue, May 11, 2010 at 9:22 AM, Tauren Mills <[email protected]>
> >> >>> wrote:
> >> >>> > I'm just getting back to this issue now, and have updated to the
> >> >>> > latest
> >> >>> > shiro snapshot.
> >> >>> > When I started working on this, I had extended
> WebRememberMeManager,
> >> >>> > but it
> >> >>> > looks like it is now depricated. What is the recommended approach
> at
> >> >>> > this
> >> >>> > time? Should I be directly extending AbstractRememberMeManager?
> >> >>> > I also wanted to point out that your example in this thread shows
> >> >>> > passing a
> >> >>> > Map to getRememberedPrincipals, but in my experience I had to pass
> a
> >> >>> > SubjectContext.  Before I proceed further, I just want to make
> sure
> >> >>> > that I'm
> >> >>> > heading down the proper path that will be supported in the future,
> >> >>> > and
> >> >>> > not
> >> >>> > implement something that I'll have to change later.
> >> >>> > Thanks!
> >> >>> > Tauren
> >> >>> >
> >> >>> >
> >> >>> >
> >> >>> >
> >> >>> >
> >> >>> >
> >> >>> > On Mon, Apr 19, 2010 at 12:14 PM, Les Hazlewood
> >> >>> > <[email protected]>
> >> >>> > wrote:
> >> >>> >>
> >> >>> >> I committed a change to how cryptography works on Friday - that
> >> >>> >> might
> >> >>> >> have done something with it (we encrypt principals by default).
> >> >>> >> However, all the test cases still passed and I know that we do
> have
> >> >>> >> some test cases around remember me cookies
> >> >>> >> (WebRememberMeManagerTest).
> >> >>> >>
> >> >>> >> Please open a Jira issue in the mean time so we don't lose it.
> >> >>> >>  I'll
> >> >>> >> try to run the sample web app(s) to see if they exhibit the same
> >> >>> >> behavior.
> >> >>> >>
> >> >>> >> Thanks!
> >> >>> >>
> >> >>> >> Les
> >> >>> >>
> >> >>> >> On Mon, Apr 19, 2010 at 10:57 AM, Tauren Mills <
> [email protected]>
> >> >>> >> wrote:
> >> >>> >> > It seems that my remember me function got broken at some point.
> >> >>> >> > All
> >> >>> >> > of
> >> >>> >> > my
> >> >>> >> > requests do not have the cookie they used to. I've tried
> logging
> >> >>> >> > off
> >> >>> >> > and
> >> >>> >> > back in again, but still no cookie.  This is
> >> >>> >> > causing getRememberedPrincipals
> >> >>> >> > to run with every single request. Obviously not good.
> >> >>> >> > Any suggestions on how to track down where the remember me
> >> >>> >> > problem
> >> >>> >> > is
> >> >>> >> > coming
> >> >>> >> > from - why I'm not getting cookies? I haven't done much of
> >> >>> >> > anything
> >> >>> >> > with
> >> >>> >> > Shiro for months now, and it used to work, so not sure what
> >> >>> >> > happened.
> >> >>> >> > Was it
> >> >>> >> > broken in some recent release that I may be using?
> >> >>> >> > Thanks,
> >> >>> >> > Tauren
> >> >>> >> > On Mon, Apr 19, 2010 at 3:41 AM, Tauren Mills
> >> >>> >> > <[email protected]>
> >> >>> >> > wrote:
> >> >>> >> >>
> >> >>> >> >> Les,
> >> >>> >> >> Thanks, I'll look into doing this. Are there any examples of
> >> >>> >> >> using
> >> >>> >> >> an
> >> >>> >> >> AuthenticationListener that I could reference?
> >> >>> >> >>
> >> >>> >> >> Tauren
> >> >>> >> >>
> >> >>> >> >> On Fri, Apr 16, 2010 at 9:10 AM, Les Hazlewood
> >> >>> >> >> <[email protected]>
> >> >>> >> >> wrote:
> >> >>> >> >>>
> >> >>> >> >>> Hi Tauren,
> >> >>> >> >>>
> >> >>> >> >>> You could implement an AuthenticationListener - I typically
> >> >>> >> >>> like
> >> >>> >> >>> to do
> >> >>> >> >>> this for these kinds of operations.
> >> >>> >> >>>
> >> >>> >> >>> Since Shiro does not count remember me as a true
> >> >>> >> >>> authentication,
> >> >>> >> >>> the
> >> >>> >> >>> AuthenticationListener will not be triggered for remember me
> >> >>> >> >>> events.
> >> >>> >> >>> To do that you would also need to implement your own
> >> >>> >> >>> RememberMeManager.  Typically subclassing the default one and
> >> >>> >> >>> updating
> >> >>> >> >>> the timestamp in the getRememberedPrincipals method would
> work:
> >> >>> >> >>>
> >> >>> >> >>> @Override
> >> >>> >> >>> public PrincipalCollection getRememberedPrincipals(Map
> >> >>> >> >>> subjectContext)
> >> >>> >> >>> {
> >> >>> >> >>>    PrincipalCollection principals =
> >> >>> >> >>> super.getRememberedPrincipals(subjectContext);
> >> >>> >> >>>    if ( principals != null ) {
> >> >>> >> >>>        int userId = principals.getPrimaryPrincipal();
> >> >>> >> >>>        //update the last login timestamp for user with this
> id
> >> >>> >> >>> here
> >> >>> >> >>>    }
> >> >>> >> >>> }
> >> >>> >> >>>
> >> >>> >> >>> The above method is called only if the current
> Subject/session
> >> >>> >> >>> does
> >> >>> >> >>> not yet have an identity associated with it.
> >> >>> >> >>>
> >> >>> >> >>> The AuthenticationListener + the above overridden method
> should
> >> >>> >> >>> do
> >> >>> >> >>> it!
> >> >>> >> >>>
> >> >>> >> >>> Cheers,
> >> >>> >> >>>
> >> >>> >> >>> Les
> >> >>> >> >>>
> >> >>> >> >>> On Thu, Apr 15, 2010 at 8:37 PM, Tauren Mills
> >> >>> >> >>> <[email protected]>
> >> >>> >> >>> wrote:
> >> >>> >> >>> > What would be the best way to update properties of a member
> >> >>> >> >>> > on
> >> >>> >> >>> > successful
> >> >>> >> >>> > authentication? Basically, there is a Member.lastLogin
> >> >>> >> >>> > property
> >> >>> >> >>> > that
> >> >>> >> >>> > I
> >> >>> >> >>> > want
> >> >>> >> >>> > updated with the current date every time a member comes
> back
> >> >>> >> >>> > to
> >> >>> >> >>> > a
> >> >>> >> >>> > site
> >> >>> >> >>> > and
> >> >>> >> >>> > logs in.  However, this should also support rememberme
> >> >>> >> >>> > authentications. I
> >> >>> >> >>> > don't necessarily want to update the lastLogin property on
> >> >>> >> >>> > every
> >> >>> >> >>> > single
> >> >>> >> >>> > interaction the user has on the site, just once for each
> >> >>> >> >>> > session.
> >> >>> >> >>> > Is there some technique in Shiro to do this, a callback of
> >> >>> >> >>> > some
> >> >>> >> >>> > sort,
> >> >>> >> >>> > or
> >> >>> >> >>> > some other method? Or should I be doing this in my
> >> >>> >> >>> > application?
> >> >>> >> >>> > Also, I can't seem to view much of the documentation. All
> the
> >> >>> >> >>> > links
> >> >>> >> >>> > on
> >> >>> >> >>> > the
> >> >>> >> >>> > following page require an Apache login. Is it supposed to
> be
> >> >>> >> >>> > this
> >> >>> >> >>> > way?
> >> >>> >> >>> > http://incubator.apache.org/shiro/core.html
> >> >>> >> >>> > Thanks!
> >> >>> >> >>> > Tauren
> >> >>> >> >>> >
> >> >>> >> >>> >
> >> >>> >> >>
> >> >>> >> >
> >> >>> >> >
> >> >>> >
> >> >>> >
> >> >>
> >> >
> >> >
> >
> >
>

Reply via email to