Les, I'm really interested about your suggestion to use Shiro's native session for my use case. I just didn't understand how I could do that. Can you elaborate on you thoughts a bit?
/Bengt 2011/11/11 Bengt Rodehav <[email protected]> > Les, > > I couldn't see how I could disable the servlet container's default > updating of the lastAccessedTime. The way I understood it this was not > being done by Shiro but by Jetty (in my case). How would you suggest that I > solve something like this? > > This is what I wanted to accomplish: > > I want to provide a URL ("checkLogin") that can be called without the > lastAccessedTime being updated. The use case is to allow the web browser to > poll the server in order to check whether the session has been terminated. > If it has been terminated then a login dialog would automatically appear. > With the default behaviour, every call to the "checkLogin" URL would update > the lastAccessedTime and the session would never time out which would > defeat the purpose of calling the "checkLogin". > > The way I interpreted the implementation of "updateSessionLastAccessTime" > was that it ensured that the lastAccessedTime would be updated even if > Shiro's native session were used instead of the web session. I want the > right opposite: I want to be able to prevent the lastAccessedTime to be > updated for certain URL's and I can't see how I can prevent the servlet > container from doing that. > > How can I solve this by using Shiro's native sessions? > > /Bengt > > > 2011/11/11 Les Hazlewood <[email protected]> > >> Hi Bengt, >> >> Why go through all of that - why not use Shiro's native session >> support (which I assume would give you the results you want)? >> >> Les >> >> P.S. the 'updateSessionLastAccessTime' was added to support Shiro's >> native session needs in a web environment. It ensures sessions behave >> correctly in a web environment (at least according to what the Servlet >> spec implies). >> >> On Fri, Nov 11, 2011 at 5:01 AM, Bengt Rodehav <[email protected]> wrote: >> > Manoj, >> > This is what I ended up doing: >> > The session timeout is handled by the underlying servlet container >> (Jetty in >> > my case) not by Shiro. The code you pointed me to is only used when >> Shiro >> > takes care of the session handling (not in a servlet context). >> > Unfortunately there is no way to set the lastAccessedTime in a servlet >> > container. The API only includes a getter. Therefore, I don't see any >> way of >> > stopping Jetty from updating the lastAccessedTime. I therefore disable >> the >> > standard session timeout (by setting it to -1). I then implement my own >> > session timeout. >> > I created my own subclass from IniShiroFilter and made an override of >> the >> > method "updateSessionLastAccessTime". I create my own session attribute >> for >> > storing the lastUsed time. In my "updateSessionLastAccessTime" I update >> that >> > attribute unless the request path is my special path ("checkLogin" that >> > should be called without updating lastUsed). >> > In that method I also check if the session should expire (I have a >> > configurable timeout for this). Unless the request path was either of >> > "login" or "logout", I end the session if the timeout has expired. >> > This solution seems to work fine although I think I've had to "roll my >> own" >> > a bit too much. Perhaps functionality like this could make it into >> Shiro? I >> > think the usecase should be useful for others as well. >> > /Bengt >> > >> > 2011/11/10 Bengt Rodehav <[email protected]> >> >> >> >> OK - thanks Manoj, >> >> I'll take a deeper look in the code. >> >> /Bengt >> >> >> >> 2011/11/9 Manoj Khangaonkar <[email protected]> >> >>> >> >>> Hi Bengt, >> >>> >> >>> The doFilterInternal method of AbstractShiroFilter starts the chain of >> >>> code that >> >>> extracts the sessionid from the request, locates the session, creates >> >>> the WebDelegatingSubject >> >>> whose session is touched. >> >>> >> >>> To get the behaviour you need, you might need to override some of this >> >>> code >> >>> >> >>> Manoj >> >>> >> >>> On Wed, Nov 9, 2011 at 12:50 AM, Bengt Rodehav <[email protected]> >> wrote: >> >>> > Hello Manoj, >> >>> > I use my own subclass of FormAuthenticationFilter. I've changed the >> >>> > behaviour of onAccessDenied() so that a 401 is returned since I do >> not >> >>> > want >> >>> > a redirect to a login URL. It's an Ajax application so I don't want >> a >> >>> > page >> >>> > reload. This seems to work. >> >>> > My first idea was to just have a special GET Url >> >>> > (.../session/checkLogin) >> >>> > that the client would call. I assume that the web browser will send >> the >> >>> > session cookie (like it always does). On the server side I'm not >> clear >> >>> > of >> >>> > what exactly happens. However, since there is a last used property >> on >> >>> > the >> >>> > sesssion and I have set the session timeout, I assumed that all >> calls >> >>> > within >> >>> > a session (determined from the session cookie) would "automagically" >> >>> > update >> >>> > the last used timestamp. Not sure if this is Shiro functionality or >> >>> > general >> >>> > Jetty functionality (Jetty is used for the OSGi http service that >> I'm >> >>> > using). >> >>> > It's not clear to me how I can tell (Shiro or Jetty?) that this >> >>> > particular >> >>> > call should not "count". You're saying that >> subject.isAuthenticated() >> >>> > does >> >>> > not touch the session but I would guess that >> >>> > calling SecurityUtils.getSubject() to get the subject needs the >> session >> >>> > to >> >>> > work. >> >>> > When exactly is the last used property updated? >> >>> > BTW, I have a "login" method (POST .../session/login) that looks >> >>> > something >> >>> > like this: >> >>> > String username = theRequest.getParameter("j_username"); >> >>> > String password = theRequest.getParameter("j_password"); >> >>> > LoginStatus status = getStatus(); >> >>> > if (!getStatus().isAuthenticated()) { >> >>> > UsernamePasswordToken token = new >> UsernamePasswordToken(username, >> >>> > password); >> >>> > Subject currentUser = SecurityUtils.getSubject(); >> >>> > try { >> >>> > currentUser.login(token); >> >>> > status = new LoginStatus(currentUser.isAuthenticated(), >> >>> > currentUser.getPrincipal().toString(), currentUser >> >>> > .getPrincipal().toString()); >> >>> > HttpSession session = theRequest.getSession(); >> >>> > if (session != null) { >> >>> > >> session.setMaxInactiveInterval(mService.getSessionTimeout()); >> >>> > } >> >>> > } catch (AuthenticationException e) { >> >>> > status = new LoginStatus(false, null, null); >> >>> > } >> >>> > } >> >>> > Thus I set the session timeout on the HttpSession after a successful >> >>> > login. >> >>> > /Bengt >> >>> > >> >>> > 2011/11/8 Manoj Khangaonkar <[email protected]> >> >>> >> >> >>> >> Hi Bengt, >> >>> >> >> >>> >> How do you plan on doing checkLogin ? >> >>> >> >> >>> >> If you use subject.isAuthenticated() , it does not touch the >> session. >> >>> >> >> >>> >> If you use an authenticationFilter like the >> FormAuthenticationFilter, >> >>> >> it can detect that the session has timed out >> >>> >> and redirect the request to a login url >> >>> >> >> >>> >> Manoj >> >>> >> >> >>> >> >> >>> >> On Tue, Nov 8, 2011 at 11:59 AM, Bengt Rodehav <[email protected]> >> >>> >> wrote: >> >>> >> > Seems like I've been bombarding this list lately. I'm quite new >> to >> >>> >> > Shiro >> >>> >> > which is why I ask all these silly questions. Must say that I'm >> very >> >>> >> > pleased >> >>> >> > so far. Shiro has turned out to be much easier to use then Spring >> >>> >> > Acegi >> >>> >> > that >> >>> >> > I have been using in the past. >> >>> >> > Anyway, I'm using Shiro 1.1 to handle authentication for an OSGi >> >>> >> > based >> >>> >> > web >> >>> >> > application using the http service in Apache Karaf. >> >>> >> > Currently my web application will return status 401 when trying >> to >> >>> >> > access >> >>> >> > resources that requires an authenticated user in case the session >> >>> >> > does >> >>> >> > not >> >>> >> > contain an authenticated user. I would like to enhance the web >> >>> >> > application >> >>> >> > so that the client (the browser) can periodically (e g once a >> minut) >> >>> >> > can >> >>> >> > check whether a user is still logged in. That way, if a user >> leaves >> >>> >> > the >> >>> >> > application for a while, I can display a login dialog so that the >> >>> >> > user >> >>> >> > can >> >>> >> > clearly see that s/he has been logged out. >> >>> >> > The problem is that if the client calls my "checkLogin" method in >> >>> >> > the >> >>> >> > context of the current session once a minute then the session >> will >> >>> >> > never >> >>> >> > time out since the last used timestamp will be updated on each >> call. >> >>> >> > Is >> >>> >> > there a best practice to accomplish this? I'm not sure if it's >> >>> >> > possible >> >>> >> > to >> >>> >> > make a call "outside" of the session. I was thinking about saving >> >>> >> > the >> >>> >> > last >> >>> >> > used timestamp in another session attribute and then restore the >> >>> >> > real >> >>> >> > last >> >>> >> > used timestamp from my special attribute after invoking my >> >>> >> > "checkLogin" >> >>> >> > method. Not sure if that would work and thought it might be wise >> to >> >>> >> > ask >> >>> >> > if >> >>> >> > anyone has done something similar before. >> >>> >> > /Bengt >> >>> >> >> >>> >> >> >>> >> >> >>> >> -- >> >>> >> http://khangaonkar.blogspot.com/ >> >>> > >> >>> > >> >>> >> >>> >> >>> >> >>> -- >> >>> http://khangaonkar.blogspot.com/ >> > >
