Hi, Yes, this can be confusing for a first-time Shiro user, and it is something Shiro could probably improve upon:
Shiro currently uses the javax.servlet.Filter API mostly for filtering - not really for configuration/initialization. Most config is expected to be done in shiro.ini (or spring.xml or Guice .java or whatever) since these mechanisms are already far more powerful than web.xml configuration. So, instead of relying on the ServletContext/FilterConfig for config, where you have to 'pull' values from a known location, you can inject them and your code does not need to know how config functions. E.g.: myFilter.someProperty = someValue ... That being said, it should probably be a configurable option to propagate the ServletContext to filters declared in shiro.ini. If you feel like you'd like this behavior instead of using the other config mechanisms, please open a Jira issue and we can address it for the next release. Note however that the Filter instances in shiro.ini are created when a ServletContext is available - not when a FilterConfig is available. This is because the Shiro WebEnvironment starts up via a Servlet Context Listener - not as a result of the Shiro Filter starting up. This could be addressed, it's just that no one has asked for it to function differently than it does currently. HTH, -- Les Hazlewood CTO, Stormpath | http://stormpath.com | 888.391.5282 twitter: @lhazlewood | http://twitter.com/lhazlewood blog: http://leshazlewood.com stormpath blog: http://stormpath.com/blog/ On Mon, Apr 16, 2012 at 1:25 PM, drmike01 <[email protected]> wrote: > 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.
