2014-02-09 4 views
0

Я создаю rest api, используя Jersey 2.5.1. Я использую HK2 для инъекций зависимостей. Позже я решил использовать Apache Shiro для аутентификации и авторизации.HK2 инъекции зависимостей с Джерси 2 и Apache Shiro

При создании своего собственного царства Сиро я столкнулся с некоторыми проблемами. В моем мире я хотел ввести зависимость. Однако, когда я запускал приложение, зависимость не была решена.

Вот мои настройки:

web.xml

<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" 
    version="3.0"> 

<listener> 
    <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class> 
</listener> 

<servlet> 
    <servlet-name>MyApplication</servlet-name> 
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> 
    <init-param> 
     <param-name>javax.ws.rs.Application</param-name> 
     <param-value>my.app.api.MyApplication</param-value> 
    </init-param> 
    <load-on-startup>1</load-on-startup> 
</servlet> 
<servlet-mapping> 
    <servlet-name>MyApplication</servlet-name> 
    <url-pattern>/*</url-pattern> 
</servlet-mapping> 

<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> 

shiro.ini

[main] 

authcBasicRealm = my.app.api.MyCustomRealm 
matcher = my.app.api.MyCustomCredentialsMatcher 
authcBasicRealm.credentialsMatcher = $matcher 
cacheManager = org.apache.shiro.cache.MemoryConstrainedCacheManager 
securityManager.cacheManager = $cacheManager 

[urls] 

/** = authcBasic 

MyApplication.java

public class MyApplication extends ResourceConfig { 
    public MyApplication() { 
     register(new ApplicationBinder()); 
     packages(true, "my.app.api"); 
    } 
} 

ApplicationBinder.java

public class ApplicationBinder extends AbstractBinder { 
    @Override 
    protected void configure() { 
     bind(UserDAO.class).to(new TypeLiteral<Dao<User>>(){}); 
     bind(RealDatasource.class).to(DataSource.class); 
    } 
} 

MyCustomRealm.java

public class MyCustomRealm extends JdbcRealm { 

    @Inject DataSource source; 

    public MyCustomRealm() { 
     super(); 
    } 

    @PostConstruct 
    private void postConstruct() { 
     // postConstruct is never executed 
     setDataSource(source); 
    } 
} 




Таким образом, проблема заключается в том, что источник не впрыскивается в MyCustomRealm. Все другие классы, которые не созданы Shiro, получают свои зависимости, вводимые. Может ли проблема заключаться в том, что Shiro создает мой CustomRealm через ini-файл?

ответ

1

я столкнулся с подобным вопросом, и, в то время как это, вероятно, больше не является проблемой для вас , Я хотел бы обеспечить работу, которую я использовал.

Вопрос является собственностью MyCustomRealm. Он создается shiro в org.apache.shiro.web.env.EnvironmentLoaderListener, читая INI-файл, который выходит за рамки поставщика hk2 в сервлете Джерси.

Включение зависимостей выполняется только в том случае, если объект предоставляется службой ServiceLocator от hk2. Широ не знает об этом локаторе и только создает экземпляр MyCustomRealm с его конструктором по умолчанию.

Я работал вокруг этого путем реализации org.glassfish.jersey.server.spi.ContainerLifecycleListener, который получает дескриптор ServiceLocator и Широ SecurityManager (через ServletContext, который зарегистрирован в ServiceLocator). Затем он вручную вводит данные в область, созданную сиро.

Если вам интересно, я могу опубликовать код как сущность.

+0

Привет, спасибо за ответ. Как вы сказали, это уже не проблема для меня, так как я больше не работаю в этой базе кода. Тем не менее, приятное решение – ulejon

+1

@space Я знаю, что это старый вопрос, но меня бы интересовала суть, если у вас все еще есть ваш пример? –

1

Одна проблема, которую я вижу в MyCustomRealm, заключается в том, что вы ожидаете, что DataSource будет заполнен во время построения. Существует два способа решения этой проблемы; один - использовать инъекцию конструктора, а другой - использовать конструкцию сообщения. Здесь будет использовать инъекции конструктор:

public class MyCustomRealm extends JdbcRealm { 

    private final DataSource source; 

    @Inject 
    public MyCustomRealm(DataSource source) { 
     super(); 

     this.source = source; 

     // source does not get injected 
     setDataSource(source); 
    } 
} 

Вот как вы бы сделать это с postConstruct:

public class MyCustomRealm extends JdbcRealm { 

    @Inject DataSource source; 

    public MyCustomRealm() { 
     super(); 
    } 

    @javax.annotation.PostConstruct 
    private void postConstruct() { 
     // source does not get injected 
     setDataSource(source); 
    } 
} 
+0

Hi. Спасибо, что нашли время ответить!К сожалению, это не сработало. Я попытался использовать @PostConstruct (я отредактировал свой пост), однако метод postConstruct() никогда не выполняется. – ulejon

Смежные вопросы