在我正在构建的应用程序中,我们使用直接的 Java 6 EE 和 JBoss(没有 Spring 等),以及 JPA/Hibernate、JSF、CDI 和 EJB。
我还没有找到很多好的通用安全解决方案(欢迎提出建议),但我发现最好的选择是 Apache Shiro。
然而,这似乎有许多缺点。您可以在Balus C 的网站上阅读其中的一些内容:
https://balusc.omnifaces.org/2013/01/apache-shiro-is-it-ready-for-java-ee-6.html
但是我偶然发现了另一个大问题,这里已经提到过依赖注入和代理。
基本上,我有一个写得很好的基于 JPA 的 UserDAO,它提供了身份验证所需的一切。我的数据库在 persistence.xml 和 mydatabase-ds.xml(用于 JBoss)中整齐地配置。
再次复制所有这些配置信息并将用户表查询添加到 shiro.ini 似乎很愚蠢。所以这就是为什么我选择编写自己的 Realm 而不是使用 JdbcRealm。
我的第一次尝试是继承 AuthorizingRealm ......类似于:
@Stateless
public MyAppRealm extends AuthorizingRealm {
@Inject private UserAccess userAccess;
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken token) throws AuthenticationException {
UsernamePasswordToken userPassToken = (UsernamePasswordToken) token;
User user = userAccess.getUserByEmail(userPassToken.getUsername());
if (user == null) {
return null;
}
AuthenticationInfo info = new SimpleAuthenticationInfo();
// set data in AuthenticationInfo based on data from the user object
return info;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// TODO
return null;
}
}
所以这很糟糕,因为 MyAppRealm 不能被代理,因为在类层次结构的父类中有一个 final init() 方法。
我的第二次尝试是让 MyAppRealm 实现所有需要的接口,并将它们委托给 AuthorizingRealm 实例。我不喜欢这个,但不妨试一试。
这让我更进一步,webapp 启动了,但仍然不足。原因是在配置文件 shiro.ini 中,我为我的领域指定了类:
myAppRealm = com.myapp.MyAppRealm
这几乎告诉我 Shiro 将负责创建 MyAppRealm 实例。因此,它不会由 CDI 管理,因此不会被注入,这正是我所看到的。
我已经看到了这个 SO answer,但我看不出它是如何工作的,因为 AuthorizingRealm 的子类将再次继承最终的 init() 方法,这意味着子类不能被代理。
关于如何解决这个问题的任何想法?