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
> >>> >> >>> >
> >>> >> >>> >
> >>> >> >>
> >>> >> >
> >>> >> >
> >>> >
> >>> >
> >>
> >
> >
>