我正在使用Jersey 2.5.1创建一个rest api。我正在使用HK2进行依赖注入。后来我决定使用Apache Shiro进行身份验证和授权。
在创建我自己的自定义Shiro Realm时遇到了一些问题。在我的领域,我想注入依赖。但是,当我运行我的应用程序时,依赖关系未得到解决。
这是我的设置:
的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是通过ini文件创建我的CustomRealm吗?
答案 0 :(得分:1)
我在MyCustomRealm中看到的一个问题是,您希望在构建时填写DataSource。有两种方法可以解决这个问题;一种是使用构造函数注入,另一种是使用post构造。这里将使用构造函数注入:
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);
}
}
答案 1 :(得分:1)
我遇到了类似的问题,虽然这对您来说可能不再是一个问题,但我想提供我使用过的解决方法。
问题是MyCustomRealm
的所有权。它是由shiro在org.apache.shiro.web.env.EnvironmentLoaderListener
中通过读取在Jersey servlet中hk2提供程序范围之外的ini文件创建的。
只有在hk2的ServiceLocator提供对象时才会执行依赖注入 - shiro不知道此定位器,只使用其默认构造函数构造MyCustomRealm
的实例。
我通过实现一个org.glassfish.jersey.server.spi.ContainerLifecycleListener
来解决这个问题,该ServletContext
获取了ServiceLocator和shiro的SecurityManager的句柄(通过ServiceLocator
注册的[<title>, <date>],
)。然后它手动将数据注入shiro创建的领域。
如果您有兴趣,我可以将代码作为要点发布。