This is what I had to write to achieve this. Perhaps the developers of
Shiro might consider finding a way to make it easier?
Stephen

public final class ShiroSecurityEnvironmentLoader extends
EnvironmentLoaderListener {

  @Override
  protected WebEnvironment createEnvironment(ServletContext servletContext) {
    ShiroWebEnvironment environment = new ShiroWebEnvironment();
    environment.setServletContext(servletContext);
    String configLocations =
StringUtils.trimToNull(servletContext.getInitParameter(CONFIG_LOCATIONS_PARAM));
    if (configLocations != null) {
      environment.setConfigLocations(configLocations);
    }
    environment.init();
    return environment;
  }

  //-------------------------------------------------------------------------
  /**
   * Apache Shiro web environment that re-uses the static manager.
   */
  private final class ShiroWebEnvironment extends IniWebEnvironment {
    @Override
    protected WebSecurityManager createWebSecurityManager() {
      ShiroFactory factory = new ShiroFactory();
      factory.setIni(getIni());
      WebSecurityManager wsm = (WebSecurityManager) factory.getInstance();
      Map<String, ?> beans = factory.getBeans();
      if (!CollectionUtils.isEmpty(beans)) {
        this.objects.putAll(beans);
      }
      return wsm;
    }
  }

  //-------------------------------------------------------------------------
  /**
   * Apache Shiro factory that re-uses the static manager.
   */
  private class ShiroFactory extends WebIniSecurityManagerFactory {
    @Override
    protected SecurityManager createDefaultInstance() {
      try {
        SecurityManager sm = SecurityUtils.getSecurityManager();
        if (sm instanceof WebSecurityManager) {
          return sm;
        }
        return super.createDefaultInstance();

      } catch (UnavailableSecurityManagerException ex) {
        return super.createDefaultInstance();
      }
    }
  }

}





On 14 March 2014 16:29, Dominic Farr <[email protected]> wrote:
> I agree constructor over setter every time; but that is another
> conversation.
>
> If you are using EmbeddedJetty which configures shiro's
> EnvironmentLoaderListener, I would suggest replacing, or encapsulating the
> shiro EnvironmentLoaderListener with your own ServletContextListener and
> inject your SecurityManager instance into that.
>
> I've done something similar with a Dropwizard project that uses an jetty and
> it works nicely.
>
> -d
>
>
>
>
> On 14 March 2014 16:15, Stephen Colebourne <[email protected]> wrote:
>>
>> On 14 March 2014 15:59, Dominic Farr <[email protected]> wrote:
>> > Not sure I fully understand your "component-based configuration system",
>> > so
>> > can you include your configuration at least?
>>
>> The INI configuration is uninteresting - a [urls] section setting up
>> permissions mapped to urls.
>>
>> The component-based config is complex to explain, but could be reduced
>> to the following actual java class (using psuedo code rather than real
>> code):
>>
>> public void initSystem() {
>>   // bits I am happy with
>>   MyUserDAO dao = ...
>>   MyUserRealm realm = new MyUserRealm(dao);
>>   SecurityManager sm = new DefaultWebSecurityManager(realm);
>>   SecurityUtils.setSecurityManager(sm);
>>   // bit that goes wrong
>>   Jetty jetty = new EmbeddedJetty();
>> }
>>
>> It goes wrong because embedded jetty reads web.xml and web.xml
>> includes EnvironmentLoaderListener, and that starts its own
>> SecurityManager. I want it to re-use the static one from
>> SecurityUtils.
>>
>>
>> > On PasswordMatcher question, I'm assuming you mean
>> >
>> > https://shiro.apache.org/static/1.2.2/apidocs/org/apache/shiro/authc/credential/PasswordMatcher.html
>> > Shiro uses setter inject over constructor. I think because that is how
>> > ini
>> > works. On this class there are get/set PasswordService.
>>
>> Yes I mean that PasswordMatcher. Not everyone uses the INI format for
>> everything. I'm creating an instanceof PasswordMatcher
>> programmatically, and it is a (minor) pain because it needs three
>> lines instead of one (in order to call the setter). I would consider
>> it good practice for Shiro to provide for setting common elements via
>> the constructor as well as via setters, particularly when the
>> PasswordService is the only setter and it is mandatory!
>>
>> Stephen
>>
>>
>> > On 14 March 2014 15:45, Stephen Colebourne <[email protected]> wrote:
>> >>
>> >> Hi Shiro team,
>> >> I am currently integrating Shiro into our application.
>> >>
>> >> We have our own component-based configuration system which needs to
>> >> operate as follows:
>> >> - start user database component
>> >> - start Shiro PasswordService component
>> >> - start Shiro SeurityManager component
>> >> - start embedded Jetty web server
>> >>
>> >> I can quite happily perform the first three steps, but when I start
>> >> the web server it currently reads a Shiro INI file in
>> >> IniWebEnvironment and sets up a second SecurityManager. Instead, I
>> >> want the existing static SecurityManager to be used. (I want to
>> >> continue using the INI file to setup the filters from the [main] and
>> >> [urls] section).
>> >>
>> >> Have I missed something, or do I just have to hack around with the
>> >> WebEnvironment to write a subclass that re-uses the static
>> >> SecurityManager?
>> >>
>> >> In the embedded Jetty scenario, I think most users would want to
>> >> re-use a static SecurityManager that has been separately created.
>> >>
>> >> Also, as a detail, PasswordMatcher could really do with an additional
>> >> constructor that takes the PasswordService.
>> >>
>> >> thanks
>> >> Stephen
>> >
>> >
>
>

Reply via email to