无法在自定义Apache Shiro AuthorizingRealm中@Inject我的DAO

我正在尝试将我的UserDAO注入Apache Shiro正在使用的自定义AuthorizingRealm中,但是……我得到了null。

我究竟做错了什么?

shiro.ini

[main] user = demo.shiro.security.FacesAjaxAwareUserFilter realmA = demo.shiro.security.JpaRealm credentialsMatcher = org.apache.shiro.authc.credential.SimpleCredentialsMatcher realmA.credentialsMatcher = $credentialsMatcher securityManager.realms = $realmA user.loginUrl = /pages/public/login.xhtml [users] admin = admin user = user [urls] # public files and folders /index.html = anon /resources/** = anon /pages/public/** = anon # restricted files and folders /pages/admin/** = user /pages/user/** = user 

JpaRealm.java

 public class JpaRealm extends AuthorizingRealm { @Inject private UserDao userDao; public JpaRealm() { setCredentialsMatcher(new Sha256CredentialsMatcher()); } protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authToken) throws AuthenticationException { UsernamePasswordToken token = (UsernamePasswordToken) authToken; User user = userDao.getForUsername(token.getUsername()); if (user != null) { return new SimpleAuthenticationInfo(user.getId(), user.getPassword(), getName()); } else { return null; } } protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { Long userId = (Long) principals.fromRealm(getName()).iterator().next(); User user = userDao.findByKey(userId); if (user != null) { SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); for (Role role : user.getRoles()) { info.addRole(role.getDescription()); for (Permition permition : role.getPermitions()) { info.addStringPermission(permition.getDescription()); } } return info; } else { return null; } } } 

我必须做些什么才能让CDI知道我的自定义领域内的@Inject并正确注入我的UserDAO?

Apache Shiro使用的默认EnvironmentLoaderListener不支持CDI。 解决方案是构建一个并替换web.xml中的原始引用以指向您自定义的引用。

注意: 侦听器会自动支持CDI注入,但侦听器必须通过CDI机制请求bean。 自定义侦听器将使用@Inject来请求bean,并将JpaRealm创建为CDI bean,它将注入所有依赖项。 默认的Shire侦听器不会通过@InjectJpaRealm创建为启用CDI的bean。

CustomCredentialsMatcher.java

 public class CustomCredentialsMatcher extends SimpleCredentialsMatcher { } 

CustomEnvironmentLoaderListener.java

 public class CustomEnvironmentLoaderListener extends EnvironmentLoaderListener { @Inject private JpaRealm jpaRealm; @Override protected WebEnvironment createEnvironment(ServletContext pServletContext) { WebEnvironment environment = super.createEnvironment(pServletContext); RealmSecurityManager rsm = (RealmSecurityManager) environment.getSecurityManager(); PasswordService passwordService = new DefaultPasswordService(); PasswordMatcher passwordMatcher = new PasswordMatcher(); passwordMatcher.setPasswordService(passwordService); jpaRealm.setCredentialsMatcher(passwordMatcher); rsm.setRealm(jpaRealm); ((DefaultWebEnvironment) environment).setSecurityManager(rsm); return environment; } } 

FacesAjaxAwareUserFilter.java

 public class FacesAjaxAwareUserFilter extends UserFilter { private static final String FACES_REDIRECT_XML = ""; @Override protected void redirectToLogin(ServletRequest req, ServletResponse res) throws IOException { HttpServletRequest request = (HttpServletRequest) req; if ("partial/ajax".equals(request.getHeader("Faces-Request"))) { res.setContentType("text/xml"); res.setCharacterEncoding("UTF-8"); res.getWriter().printf(FACES_REDIRECT_XML, request.getContextPath() + getLoginUrl()); } else { super.redirectToLogin(req, res); } } } 

JpaRealm.java

 public class JpaRealm extends AuthorizingRealm { private static String REALM_NAME = "jpaRealm"; @Inject private UserDao userDao; @Inject private RoleDao roleDao; @Inject private PermissionDao permissionDao; public JpaRealm() { setName(REALM_NAME); // This name must match the name in the User class's getPrincipals() method } protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authToken) throws AuthenticationException { UsernamePasswordToken token = (UsernamePasswordToken) authToken; User user = userDao.getForUsername(token.getUsername()); if (user != null) { return new SimpleAuthenticationInfo(user.getId(), user.getPassword(), getName()); } else { return null; } } protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { Long userId = (Long) principals.fromRealm(getName()).iterator().next(); User user = userDao.findByKey(userId); if (user != null) { SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); for (Role role : roleDao.getForUser(user)) { info.addRole(role.getDescription()); for (Permition permition : permissionDao.getForRole(role)) { info.addStringPermission(permition.getDescription()); } } return info; } else { return null; } } } 

shiro.ini

 [main] user = com.boss.mrfoods.security.FacesAjaxAwareUserFilter user.loginUrl = /pages/public/login.xhtml [urls] /index.html = anon /pages/index.xhtml = anon /pages/public/** = anon /pages/admin/** = user, roles[ADMIN] /pages/user/** = user, roles[USER] 

web.xml中

 ...  com.boss.mrfoods.security.CustomEnvironmentLoaderListener   ShiroFilter org.apache.shiro.web.servlet.ShiroFilter   ShiroFilter /*  ... 

jpaRealm恰好在’CustomEnvironmentLoaderListener’中为null。 我尝试在JpaRealm类上设置@Service(“JpaRealm”)注释,以便容器可以知道注入但仍然没有运气。 在任何一种情况下,JpaRealm都是null。

如果我们在Custom Realms中进行注射工作,还需要做些什么。

使用ShiroWebModule注入您的自定义Realm

 public class PocShiroModule extends ShiroWebModule { public PocShiroModule(ServletContext servletContext) { super(servletContext); } @Override protected void configureShiroWeb() { bindConstant().annotatedWith(Names.named("shiro.globalSessionTimeout")) .to(30000L); bind(Realm.class).to(JPARealm.class); } @Provides @Singleton Set provideRealmSet(Realm realm) { Set result = new HashSet(); result.add(realm); return result; } } 

在上下文侦听器中注册此模块

 public class PocGuiceServletConfig extends GuiceServletContextListener { private ServletContext context = null; @Override public void contextInitialized(ServletContextEvent servletContextEvent) { this.context = servletContextEvent.getServletContext(); super.contextInitialized(servletContextEvent); } @Override protected synchronized Injector getInjector() { return Guice.createInjector( new PocModule(), new PocShiroModule(context), new ShiroAopModule()); } }