I did some debugging of this issue, and what I found was very interesting,
and honestly confusing coming from a standard servlet frame of mind.
So AbstractFilter, which is a superclass of my LoginFilter, has an empty
protected method called onFilterConfigSet(), put there for subclasses to
initialize with, because the init() method there is final. Nowhere between
that and AuthenticatingFilter, my filter's direct superclass, touches this
method, so I tried to use it to get my servlet context. Incidentally,
AbstractShiroFilter, the superclass for both ShiroFilter and the deprecated
IniShiroFilter, makes the onFilterConfigSet() method final, however this
shouldn't be relevant to me because I don't inherit from them (I'm in the
AuthenticatingFilter chain).
What I discovered in debugging, though, is that AbstractFilter's init() and
onFilterConfigSet() methods are never actually called within the context of
my Filter. What instead happens is that ShiroFilter's init() gets called,
presumably as the only true Filter in my web.xml, and my LoginFilter,
although it is ultimately used by the app, never goes through an init()
function, and therefore never does the onFilterConfigSet() method. It's
essentially a "fake filter" from the standpoint of the servlet container,
and Shiro manages its own filter chain without calling inits on any of them.
My web.xml is below (right out of the manual):
<listener>
<listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
</listener>
<filter>
<filter-name>ShiroFilter</filter-name>
<filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ShiroFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
And my shiro.ini below:
[main]
myRealm = com.domainname.MydomainJdbcRealm
myRealm.jndiDataSourceName = jdbc/MydomainDB
myRealm.permissionsLookupEnabled=true
myRealm.authenticationQuery = select password from users where email = ?
loginFilter = com.domainname.LoginFilter
# set rememberMe timeframe to 3 days (72 hours = 60 sec x 60 min x 72 hrs)
securityManager.rememberMeManager.cookie.maxAge = 259200
[users]
[roles]
[urls]
/logout = anon
/healthcheck.html = anon
/* = loginFilter
So, my thinking now is that the only way to do what I need to do is to have
my own Filter, in addition to ShiroFilter, in the web.xml, and in that do
the database query that I need to. I could pull the WebEnvironment and all
the related info that I need from there, because I can grab the
ServletContext easily there. Alternately have a servlet that is the
destination for login attempts that does this too, but regardless the same
idea applies.
Am I missing something here, or is this what I should be expected to do? I
had thought that the filters in shiro.ini were regular servlet container
filters, especially because their AbstractFilter superclass actually
implements the javax.servlet.Filter interface, and I could put them all in
there in order to control the sequence of all of my filters better (the
manual actually suggests this to be a benefit of using this approach). If
that's not the case, and what I'm seeing above is correct, then from a
design standpoint should the filters in the AuthenticatingFilter chain
really implement the Filter interface if they don't function in that way? I
feel like I'm missing something obvious, though.
--
View this message in context:
http://shiro-user.582556.n2.nabble.com/Can-t-get-ServletContext-from-Filter-tp7468957p7471676.html
Sent from the Shiro User mailing list archive at Nabble.com.