Pax Whiteboard, ShiroFilter and error message: "No WebEnvironment found: no EnvironmentLoaderListener registered?"

170 views
Skip to first unread message

Steinar Bang

unread,
Mar 18, 2018, 3:23:46 PM3/18/18
to op...@googlegroups.com
Has anyone else been using apache shiro with the pax web whiteboard
extender? Has anyone else succeeded in making it work?

Shiro uses a filter to handle authentication and authorization for a
paths of a webapp.

I'm trying to create a ShiroFilter DS component to front a servlet
(also a DS component) when using the Pax Web Whiteboard Exctender.

It seemed to work at first, ie. I got a login windown in my application
and was able to log in (which means that shiro is working as it is
supposed to), but when I changed the name of the filter DS component it
started failing.

I don't know *why* it fails when the name is changed, but I know *how*
it fails: it fails with the error message:
No WebEnvironment found: no EnvironmentLoaderListener registered?

This is a well known and dreaded error message when using apache shiro,
see eg.
https://stackoverflow.com/questions/15645799/jetty-maven-plugin-unable-to-hot-redeploy-shiro-filter
https://stackoverflow.com/questions/15645799/jetty-maven-plugin-unable-to-hot-redeploy-shiro-filter

I have encountered this issue earlier, when I first tried to use the pax
web whiteboard extender, using my home brewed "mini dependency
injection" BundleActivator. The way I solved it make the ShiroFilter
listen for a service of type WebContainer, and create an
EnvironmentLoaderListener when a WebContainer is enabled, like this:

@Component(
property= {
HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_PATTERN+"=/ukelonn/*",
"servletNames=ukelonn"},
service=Filter.class,
immediate=true
)
public class UkelonnShiroFilter extends ShiroFilter {
private WebContainer webContainer;
private HttpContext httpcontext;
private EnvironmentLoaderListener listener;

@Reference
public void setWebContainer(WebContainer webContainer) {
createEnvironmentLoaderListenerAndDefaultContext(webContainer);
}

private void createEnvironmentLoaderListenerAndDefaultContext(WebContainer webContainer) {
if (this.webContainer == webContainer) {
return; // already registered, nothing to do
}

unregisterExistingEnvironmentLoaderListener();

this.webContainer = webContainer;

if (webContainer != null) {
httpcontext = webContainer.createDefaultHttpContext();
listener = new EnvironmentLoaderListener();
webContainer.registerEventListener(listener, httpcontext);
}
}

private void unregisterExistingEnvironmentLoaderListener() {
if (webContainer != null) {
webContainer.unregisterEventListener(listener);
listener = null;
}
}

}

This worked at first, but stopped working when I changed the name of the
class. I can see in the debugger that the UkelonnShiroFilter gets a
WebContainer injection and creates and registers an
EnvironmentLoaderListener.

But even so the ShiroFilter fails during initialization with the
following error message:
java.lang.IllegalStateException: No WebEnvironment found: no EnvironmentLoaderListener registered?

Does anyone know what I can/should do to initialize the WebEnvironment
properly for the shiro filter?

Thanks!


- Steinar

Achim Nierbeck

unread,
Mar 19, 2018, 7:09:17 AM3/19/18
to op...@googlegroups.com
Hi Steinar,

I thought that's what pax shiro is for.  [1]

regards, Achim

[1] - https://github.com/ops4j/org.ops4j.pax.shiro


--
--
------------------
OPS4J - http://www.ops4j.org - op...@googlegroups.com

---
You received this message because you are subscribed to the Google Groups "OPS4J" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ops4j+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--

Apache Member
Apache Karaf <http://karaf.apache.org/> Committer & PMC
OPS4J Pax Web <http://wiki.ops4j.org/display/paxweb/Pax+Web/> Committer & Project Lead
blog <http://notizblog.nierbeck.de/>
Co-Author of Apache Karaf Cookbook <http://bit.ly/1ps9rkS>

Software Architect / Project Manager / Scrum Master 

Alexander Rotnov

unread,
Mar 19, 2018, 9:35:51 AM3/19/18
to OPS4J
I also faces this problem, while adopt Shiro to Karaf and Pax Web. My solution - do not try to initialize filter from WebEnvironment, as in ShiroFilter.
Try to extend AbstractShiroFilter and inject to it WebSecurityManager and FilterChainResolver.

Steinar Bang

unread,
Mar 19, 2018, 11:41:30 AM3/19/18
to op...@googlegroups.com
>>>>> "'Achim Nierbeck' via OPS4J" <op...@googlegroups.com>:

> Hi Steinar,
> I thought that's what pax shiro is for. [1]

> regards, Achim

> [1] - https://github.com/ops4j/org.ops4j.pax.shiro

Hm... I've looked at this before, and I can't remember what the
conclusions were. I think I landed on there not being anything in there
that was useful to me.

Also it's quite old: last commit was in May 2014.

(Old both wrt. to Shiro and wrt. the current apache karaf stack (which
is where I use the pax web stuff))

Steinar Bang

unread,
Mar 19, 2018, 11:47:22 AM3/19/18
to op...@googlegroups.com
>>>>> Alexander Rotnov <pro...@gmail.com>:
Thanks! I will try this.

Steinar Bang

unread,
Mar 19, 2018, 6:17:29 PM3/19/18
to op...@googlegroups.com
>>>>> Steinar Bang <s...@dod.no>:
It tried it, but it's kind of weird:
1. The pax exam test that loads the servlet and filter works when run
from maven
2. The pax exam test fails when run from inside eclipse
3. The filter fails when the application is loaded into karaf 4.1.5

That the pax exam test works in one setting and fails in another hints
at something timing releated...?

But I didn't think DS components would have timing issues? They either
become active, or they don't... and a pax exam test with @Inject members
don't actually run anything until all injections have been satisifed.

Anyway, here's the component:

@Component(
property= {
HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_PATTERN+"=/ukelonn/*",
"servletNames=ukelonn"},
service=Filter.class,
immediate=true
)
public class UkelonnShiroFilter extends AbstractShiroFilter {

private static UkelonnShiroFilter instance;
private UkelonnDatabase database;
WebSecurityManager securitymanager;
FilterChainResolver resolver;

public UkelonnShiroFilter() {
instance = this;
}

@Activate
public void activate() {
setSecurityManager(securitymanager);

if (resolver != null) {
setFilterChainResolver(resolver);
}
}

@Reference
public void setUkelonnDatabase(UkelonnDatabase database) {
this.database = database;
}

public UkelonnDatabase getDatabase() {
return database;
}

@Reference
public void setSecuritymanager(WebSecurityManager securitymanager) {
this.securitymanager = securitymanager;
}

@Reference
public void setResolver(FilterChainResolver resolver) {
this.resolver = resolver;
}

public static UkelonnShiroFilter getInstance() {
return instance;
}

}

Alexander Rotnov

unread,
Mar 20, 2018, 1:11:52 PM3/20/18
to OPS4J
On Tuesday, March 20, 2018 at 1:17:29 AM UTC+3, Steinar Bang wrote:

 3. The filter fails when the application is loaded into karaf 4.1.5


What kind of fails?
In Karaf (in Felix) DS component became active and @Activate method invoked, when all dependecies are resolved. I think pax exam also waits until all dependencies are resolve. Actually, I'm unfamiliar with pax exam :)
Do you register WebSecurityManager and FilterChainResolver as a services?

Steinar Bang

unread,
Mar 20, 2018, 1:23:00 PM3/20/18
to op...@googlegroups.com
>>>>> Alexander Rotnov <pro...@gmail.com>:

> On Tuesday, March 20, 2018 at 1:17:29 AM UTC+3, Steinar Bang wrote:
>>
>>
>> 3. The filter fails when the application is loaded into karaf 4.1.5

> What kind of fails?

Well, now the pax exam tests works from inside eclipse as well as when
building with maven.

I don't know why it failed before and suddenly started working. Maybe
something was finally updated all the way into eclipse, after I had
built the project with maven from the command line.

Now it's only inside karaf it fails but when I look at the stack trace
the failure is in a different place.

> In Karaf (in Felix) DS component became active and @Activate method
> invoked, when all dependecies are resolved. I think pax exam also
> waits until all dependencies are resolve. Actually, I'm unfamiliar
> with pax exam :)

Well, Pax Exam is like karaf in this case, because I use the pax exam
karaf configuration, except for one thing: the @Inject of the services
in the pax exam test ensures that DS components are created.

> Do you register WebSecurityManager and FilterChainResolver as a services?

No I haven't. Should I? I thought Pax Whiteboard Extender handles
creating the appropriate services?

Steinar Bang

unread,
Mar 20, 2018, 2:18:22 PM3/20/18
to op...@googlegroups.com
>>>>> Steinar Bang <s...@dod.no>:

>> Do you register WebSecurityManager and FilterChainResolver as a services?

> No I haven't. Should I? I thought Pax Whiteboard Extender handles
> creating the appropriate services?

Hm... it did seem to work earlier, but now I did an experiment that
failed, and when I rolled things back the pax exam test failed and I
found this in pax exam's karaf.log:
2018-03-20T18:55:44,193 | ERROR | pool-1-thread-2 | BootFeaturesInstaller | 7 - org.apache.karaf.features.core - 4.1.2 | Error installing boot features
org.osgi.service.resolver.ResolutionException: Unable to resolve root: missing requirement [root] osgi.identity; osgi.identity=ukelonn; type=karaf.feature; version="[1.0.0.SNAPSHOT,1.0.0.SNAPSHOT]"; filter:="(&(osgi.identity=ukelonn)(type=karaf.feature)(version>=1.0.0.SNAPSHOT)(version<=1.0.0.SNAPSHOT))" [caused by: Unable to resolve ukelonn/1.0.0.SNAPSHOT: missing requirement [ukelonn/1.0.0.SNAPSHOT] osgi.identity; osgi.identity=no.priv.bang.ukelonn; type=osgi.bundle; version="[1.0.0.SNAPSHOT,1.0.0.SNAPSHOT]"; resolution:=mandatory [caused by: Unable to resolve no.priv.bang.ukelonn/1.0.0.SNAPSHOT: missing requirement [no.priv.bang.ukelonn/1.0.0.SNAPSHOT] osgi.service; effective:=active; filter:="(objectClass=org.apache.shiro.web.filter.mgt.FilterChainResolver)"]]
at org.apache.felix.resolver.ResolutionError.toException(ResolutionError.java:42) ~[?:?]
at org.apache.felix.resolver.ResolverImpl.doResolve(ResolverImpl.java:389) ~[?:?]
at org.apache.felix.resolver.ResolverImpl.resolve(ResolverImpl.java:375) ~[?:?]
at org.apache.felix.resolver.ResolverImpl.resolve(ResolverImpl.java:347) ~[?:?]
at org.apache.karaf.features.internal.region.SubsystemResolver.resolve(SubsystemResolver.java:218) ~[?:?]
at org.apache.karaf.features.internal.service.Deployer.deploy(Deployer.java:291) ~[?:?]
at org.apache.karaf.features.internal.service.FeaturesServiceImpl.doProvision(FeaturesServiceImpl.java:1233) ~[?:?]
at org.apache.karaf.features.internal.service.FeaturesServiceImpl.lambda$doProvisionInThread$0(FeaturesServiceImpl.java:1132) ~[?:?]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:?]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:?]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:?]
at java.lang.Thread.run(Thread.java:748) [?:?]

(ie. FilterChainResolver was missing)

Steinar Bang

unread,
Mar 20, 2018, 2:45:51 PM3/20/18
to op...@googlegroups.com
>>>>> Steinar Bang <s...@dod.no>:

>>>>> Steinar Bang <s...@dod.no>:
>>> Do you register WebSecurityManager and FilterChainResolver as a services?

>> No I haven't. Should I? I thought Pax Whiteboard Extender handles
>> creating the appropriate services?
[snip!]
> (ie. FilterChainResolver was missing)

Right! Both WebEnvironment and FilterChainResolver are shiro classes, so
of course I (or something else) would need to create something that
provides those services.

There is no way my code earlier could have actually worked, so something
in how I'm testing it is fooling myself (running old code, probably...).


Александр

unread,
Mar 20, 2018, 3:45:54 PM3/20/18
to op...@googlegroups.com
Thats right.  
My solution is to build shiro infrastructure (securitymanager, realms, filterchainresolver) by myself as a beans in blueprint, because I can inject to them other services (like Datasource, or EntityManager). I do not use ini file, and actually I do not use shiro in standard servlet container, because there is Spring for it :) 
But if you use shiro before, and have ini file, you can create SecurityManager by IniSecurityManagerFactory and FilterChainResolver by IniFilterChainResolverFactory and set them to your filter. All of this is better to do in activate() method of your filter.
And dont forget to install shiro bundles (shiro-core, shiro-web...)


Steinar Bang

unread,
Mar 24, 2018, 2:01:16 PM3/24/18
to op...@googlegroups.com
>>>>> Александр <pro...@gmail.com>:

> Thats right.
> My solution is to build shiro infrastructure (securitymanager, realms,
> filterchainresolver) by myself as a beans in blueprint, because I can
> inject to them other services (like Datasource, or EntityManager). I do not
> use ini file, and actually I do not use shiro in standard servlet
> container, because there is Spring for it :)
> But if you use shiro before, and have ini file, you can create
> SecurityManager by IniSecurityManagerFactory
> <https://shiro.apache.org/static/1.3.2/apidocs/src-html/org/apache/shiro/config/IniSecurityManagerFactory.html#line.46>
> and
> FilterChainResolver by IniFilterChainResolverFactory
> <https://shiro.apache.org/static/1.3.2/apidocs/src-html/org/apache/shiro/web/config/IniFilterChainResolverFactory.html#line.43>
> and
> set them to your filter. All of this is better to do in activate() method
> of your filter.
> And dont forget to install shiro bundles (shiro-core, shiro-web...)

Thanks! I'm part of the way there. I needed the
WebIniSecurityManagerFactory class instead, because AbstractShiroFilter
needs WebSecurityManager.

However I ran into a problem in that WebIniSecurityManagerFactory
doesn't like my custom realm. I get the following error message in
karaf.log of the pax exam test:
2018-03-24T18:40:56,944 | ERROR | features-1-thread-1 | ukelonn | 21 - no.priv.bang.ukelonn - 1.0.0.SNAPSHOT | [no.priv.bang.ukelonn.impl.UkelonnShiroFilter(4)] The activate method has thrown an exception
org.apache.shiro.config.ConfigurationException: Unable to set property 'realms' with value [[no.priv.bang.ukelonn.impl.UkelonnRealm@7eb8a95d]] on object of type org.apache.shiro.web.mgt.DefaultWebSecurityManager. If '[no.priv.bang.ukelonn.impl.UkelonnRealm@7eb8a95d]' is a reference to another (previously defined) object, prefix it with '$' to indicate that the referenced object should be used as the actual value. For example, $[no.priv.bang.ukelonn.impl.UkelonnRealm@7eb8a95d]
[snip!]
Caused by: java.lang.ClassCastException: no.priv.bang.ukelonn.impl.UkelonnRealm cannot be cast to org.apache.shiro.realm.Realm

Could this be OSGi class loader issue...?

The shiro.ini file looks like this:
[main]
authc.loginUrl = /
user.loginUrl = /
credentialsMatcher = org.apache.shiro.authc.credential.Sha256CredentialsMatcher
# base64 encoding, not hex in this example:
credentialsMatcher.storedCredentialsHexEncoded = false
credentialsMatcher.hashIterations = 1024
ukelonnRealm = no.priv.bang.ukelonn.impl.UkelonnRealm
ukelonnRealm.credentialsMatcher = $credentialsMatcher
securityManager.realms = $ukelonnRealm
[users]

[urls]
/ = authc
/* = user


The realm definition is:
public class UkelonnRealm extends AuthorizingRealm
Following the inheritance:
AuthorizingRealm extends AuthenticatingRealm
AuthenticatingRealm extends CachingRealm implements Initializable
CachingRealm implements Realm, Nameable, CacheManagerAware, LogoutAware

The Realm interface in the last line is org.apache.shiro.realm.Realm.

I have checked the Import-Package of the manifest.mf in my application's
bundle, and as far as I can tell, it imports the org.apache.shiro.realm
package:
Import-Package: no.priv.bang.ukelonn,javax.servlet.http;version="[2.6.0,
4.0.0)",com.vaadin.server;version="[7.6,8)",com.vaadin.addon.touchkit.s
erver,com.vaadin.addon.touchkit.ui,com.vaadin.annotations;version="[7.6
,8)",com.vaadin.data;version="[7.6,8)",com.vaadin.data.util;version="[7
.6,8)",com.vaadin.data.util.converter;version="[7.6,8)",com.vaadin.data
.validator;version="[7.6,8)",com.vaadin.navigator;version="[7.6,8)",com
.vaadin.ui;version="[7.6,8)",javax.servlet;version="[3.1,4)",org.apache
.karaf.shell.api.action;version="[4.1,5)",org.apache.karaf.shell.api.ac
tion.lifecycle;version="[4.1,5)",org.apache.shiro;version="[1.3,2)",org
.apache.shiro.authc;version="[1.3,2)",org.apache.shiro.authz;version="[
1.3,2)",org.apache.shiro.config;version="[1.3,2)",org.apache.shiro.cryp
to;version="[1.3,2)",org.apache.shiro.crypto.hash;version="[1.3,2)",org
.apache.shiro.realm;version="[1.3,2)",org.apache.shiro.subject;version=
"[1.3,2)",org.apache.shiro.util;version="[1.3,2)",org.apache.shiro.web.
config;version="[1.3,2)",org.apache.shiro.web.filter.mgt;version="[1.3,
2)",org.apache.shiro.web.mgt;version="[1.3,2)",org.apache.shiro.web.ser
vlet;version="[1.3,2)",org.osgi.service.log;version="[1.3,2)",com.vaadi
n.addon.touchkit.gwt.client,VAADIN.widgetsets.com.vaadin.addon.touchkit
.gwt.TouchKitWidgetSet,com.vaadin.addon.touchkit.gwt.client.theme,com.v
aadin.addon.touchkit.gwt.client.vcom.popover,assets,com.vaadin.addon.to
uchkit.settings,com.vaadin.addon.touchkit.gwt.client.ui,com.vaadin.addo
n.touchkit.gwt,com.vaadin.addon.touchkit.gwt.client.vcom,com.vaadin.add
on.touchkit.annotations,com.vaadin.addon.touchkit.gwt.client.communicat
ion,com.vaadin.addon.touchkit.gwt.client.theme.fonts,com.vaadin.addon.t
ouchkit.gwt.client.vcom.navigation,VAADIN.widgetsets;version="[7.6,8)",
com.vaadin.addon.touchkit.extensions,com.vaadin.shared;version="[7.6,8)
",VAADIN.widgetsets.com.vaadin.addon.touchkit.gwt.TouchKitWidgetSet.def
erredjs.0A32B241463C3CF770B8CD52599C1C21,com.vaadin.addon.touchkit.gwt.
client.offlinemode,com.vaadin.addon.touchkit.service,com.vaadin.addon.t
ouchkit.gwt.client.theme.img,VAADIN.themes

All hints, guesses and ideas are appreciated!

Thanks!

Steinar Bang

unread,
Mar 26, 2018, 5:59:04 PM3/26/18
to op...@googlegroups.com
>>>>> Steinar Bang <s...@dod.no>:
Probably a class loader issue. It now works:
https://github.com/steinarb/ukelonn/blob/4be88dab9fd97d449592cd46fb1ab9b5762b3b36/ukelonn.bundle/src/main/java/no/priv/bang/ukelonn/impl/UkelonnShiroFilter.java#L64

I had to create the realm using code rather than in the shiro.ini file:
https://github.com/steinarb/ukelonn/blob/4be88dab9fd97d449592cd46fb1ab9b5762b3b36/ukelonn.bundle/src/main/java/no/priv/bang/ukelonn/impl/UkelonnShiroFilter.java#L92
https://github.com/steinarb/ukelonn/commit/4be88dab9fd97d449592cd46fb1ab9b5762b3b36#diff-d4776a0758751afbed78ab9a334bc8ce

I also ran into a problem with Shiro's Ini file loading from the
classpath. It actually worked in karaf in the pax exam integration
test, but not in karaf actual. So I had to explicitly find the
shiro.ini resource from the classloader of my AbstractShiroFilter DS
component:
https://github.com/steinarb/ukelonn/blob/4be88dab9fd97d449592cd46fb1ab9b5762b3b36/ukelonn.bundle/src/main/java/no/priv/bang/ukelonn/impl/UkelonnShiroFilter.java#L51

Reply all
Reply to author
Forward
0 new messages