In an app I'm building we're using straight Java 6 EE and JBoss (no Spring, etc), with JPA/Hibernate, JSF, CDI and EJBs.
I haven't found many good general security solutions (recommendations are welcome), but the best bet I found is Apache Shiro.
However this seems to have a number of shortcomings. Some of which you can read about at Balus C's site:
http://balusc.blogspot.com/2013/01/apache-shiro-is-it-ready-for-java-ee-6.html
But I've stumbled on another big problem which is already mentioned here regarding dependency injection and proxying.
Basically I have a nicely written JPA-based UserDAO that provides everything necessary for authentication. My database is neatly configured in persistence.xml and mydatabase-ds.xml (for JBoss).
It seems silly to duplicate all this config info a second time and add user tables queries into shiro.ini. So this is why I have opted to write my own Realm instead of using JdbcRealm.
My first attempt at this was to subclass AuthorizingRealm...something like:
@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;
}
}
So this fails pretty bad, because MyAppRealm cannot be proxied because there is a final init() method in a parent class up the class hierarchy.
My second attempt was to have MyAppRealm implement all the needed interfaces and just delegate them to instance of AuthorizingRealm. I didn't like this, but might as well give it a try.
This gets me further, the webapp starts up, but still falls short. The reason is in the config file, shiro.ini, I specify the class for my realm:
myAppRealm = com.myapp.MyAppRealm
This pretty much tells me that Shiro will be responsible for creating the MyAppRealm instance. Therefore it will not be CDI managed and thus not injected, which is exactly what I'm seeing.
I've seen this SO answer, but I don't see how it could possibly work because again a subclass of AuthorizingRealm will inherit a final init() method meaning the subclass cannot be proxied.
Any thoughts on how I can get around this?
See Question&Answers more detail:
os