Hello all,

I'm using Shiro on a proxy servlet that relays requests to another web module 
containing REST web services, provided the user is authenticated *or* 
remembered, i.e. I currently treat those two states the same. This works all 
nicely, but I'm having some trouble dealing with the situation when an existing 
user gets deleted.

As I see it, the Shiro "user" filter (as defined in my shiro.ini) still creates 
a valid Subject using the supplied rememberMe cookie. My code that checks the 
validity of the Subject therefore still executes the proxy request. It is in 
the web service module that the actual check against the database takes place 
(also using Shiro), which then results in a HTTP 401 response.

My problem is that I can't find a clean way to programatically delete the 
rememberMe cookie *and* the Session owned by the deleted Subject. In my proxy 
servlet, I can detect the HTTP 401 response and perform a Subject.logout() in 
reaction to that, but then I run into the problem that there are often multiple 
parallel requests running, which are created concurrently by the frontend 
AngularJS single page app. So if I do a Subject.logout() on one of those 
threads, the other threads can run into exceptions when doing a check like 
Subject.isAuthenticated() or Subject.isRemembered(), as those are ultimately 
delegated to the underlying HttpSession. The stack trace looks like this:

java.lang.IllegalStateException: getAttribute: Session already invalidated
        at 
org.apache.catalina.session.StandardSession.getAttribute(StandardSession.java:1355)
        at 
org.apache.catalina.session.StandardSessionFacade.getAttribute(StandardSessionFacade.java:152)
        at 
org.apache.shiro.web.session.HttpServletSession.getAttribute(HttpServletSession.java:146)
        at 
org.apache.shiro.session.ProxiedSession.getAttribute(ProxiedSession.java:121)
        at 
org.apache.shiro.subject.support.DelegatingSubject.getRunAsPrincipalsStack(DelegatingSubject.java:469)
        at 
org.apache.shiro.subject.support.DelegatingSubject.getPrincipals(DelegatingSubject.java:153)
        at 
org.apache.shiro.subject.support.DelegatingSubject.isRemembered(DelegatingSubject.java:297)
        at 
com.lso.proxy.AuthenticatingProxyServlet.service(AuthenticatingProxyServlet.java:65)
        [...]

Issuing another Subject.logout() therefore also results in an exception.

While I can catch and swallow all those exceptions, there's another log entry 
that's ugly to say the least, which looks like this:

WARN: WELD-000712: Unable to dissociate context 
org.jboss.weld.context.http.LazyHttpConversationContextImpl@307f4035 when 
destroying request org.apache.catalina.connector.RequestFacade@72507072

I'm using GlassFish 4.1 and I believe the explanation for this warning can be 
found here: https://issues.jboss.org/browse/WELD-1813. As I don't use CDI in 
this web module *yet*, it seems I would not be affected from the mentioned 
thread corruption even though GlassFish 4.1 ships with an affected version of 
Weld, but it would still be nicer to get rid of that warning altogether.

Does someone know a more elegant, straight-forward way to deal with this?

I've found a thread about programmatic forgetting of a remembered user here: 
http://shiro-user.582556.n2.nabble.com/How-to-force-a-remembered-user-to-be-forgotten-td7579089.html.
 But the problem I see with the proposed solution of calling 
RememberMeManager.forgetIdentity() is that the Session doesn't get invalidated 
at the same time. So the AngularJS app will keep sending the JSESSIONID cookie 
and the Subject will still be "authenticated", if they had logged in to the 
same Session before the user got deleted. Therefore I believe I really have to 
invalidate the Session at the same time.


Best regards,
Joachim Kanbach

Reply via email to