Monday, March 17, 2008
Open Hibernate Question
Open question: I see in the Hibernate documentation that Hibernate's EntityManager is "similar to" Hibernate's Session interface. But it isn't clear when I should be using one versus the other. I'm using the EntityManager now and everything's going fine. But I want to make sure I'm doing this The Right Way so that I don't have to rip it apart and rewrite it in three months when I better understand the business problems I'm fighting. Any readers have any insight?
Friday, March 7, 2008
Acegi: It Makes Sense Now
I was trying to write a massive security infrastructure beast. I don't need to do that.
The first thing I've done since the last post is to write my own 'SecurityService' class that implements the UserDetailsService interface. UserDetailsService has just one method -- UserDetails loadUserByUsername(String). So it takes a username and loads that whole user object.
Well this confused me. Where the hell, I thought, does the password get dealt with here?
The answer is that the password is handled by the Authentication Provider (in this example, an org.acegisecurity.providers.dao.DaoAuthenticationProvider). So this particular authentication provider accepts a username and password, uses the username to pull the UserDetails data out of the UserDetailsService, and then (in memory) (presumably) compares the submitted password to the password returned from the UserDetails object's getPassword() method.
I'm not thrilled by this implementation, because it assumes that passwords will be stored in plaintext! They shouldn't be.
Anyway, I verified all of this by building out a deliberately stupid implementation of the UserDetailsService and wiring it into my application -- specifically I wrote one that always returns the same UserDetails object, with a known and bogus username and password. I tested this and it worked, so it all makes more sense to me now. Next step is to rewrite my bogus UserDetailsService to talk to my actual application code and return real user objects.
Down the road a bit I'm probably going to have to look at the other authentication providers, so that I can handle encrypted passwords. But in the interim this is good progress.
Stupid side note: for some reason, whenever I log in, users are getting redirected to an image file the first time.
The first thing I've done since the last post is to write my own 'SecurityService' class that implements the UserDetailsService interface. UserDetailsService has just one method -- UserDetails loadUserByUsername(String). So it takes a username and loads that whole user object.
Well this confused me. Where the hell, I thought, does the password get dealt with here?
The answer is that the password is handled by the Authentication Provider (in this example, an org.acegisecurity.providers.dao.DaoAuthenticationProvider). So this particular authentication provider accepts a username and password, uses the username to pull the UserDetails data out of the UserDetailsService, and then (in memory) (presumably) compares the submitted password to the password returned from the UserDetails object's getPassword() method.
I'm not thrilled by this implementation, because it assumes that passwords will be stored in plaintext! They shouldn't be.
Anyway, I verified all of this by building out a deliberately stupid implementation of the UserDetailsService and wiring it into my application -- specifically I wrote one that always returns the same UserDetails object, with a known and bogus username and password. I tested this and it worked, so it all makes more sense to me now. Next step is to rewrite my bogus UserDetailsService to talk to my actual application code and return real user objects.
Down the road a bit I'm probably going to have to look at the other authentication providers, so that I can handle encrypted passwords. But in the interim this is good progress.
Stupid side note: for some reason, whenever I log in, users are getting redirected to an image file the first time.
Back with Acegi
After a ColdFusion-induced layoff I'm back hacking at Acegi Security.
At this point I have a simple (very simple) Struts 2 application in place and I'm applying Acegi Security to it.
What I've done so far is taken the Acegi Petclinic Tutorial and applied it to my application. I used just about the simplest possible security implementation there -- I changed some names in their default users.properties file and implemented properties-file-driven security.
So far it does work, though -- the login page is exposed to all comers, while the more secure pages deeper in the app are hidden. Routing to the "landing" page upon login works correctly as well.
Next I want to change authentication so that it looks at my users table instead of looking at the properties file. I'll continue to assume just two levels of authorization (anonymous and logged-in user). The Acegi Security reference documentation suggests that I'm going to want to implement the UserDetailsService interface... but of course UserDetailsService doesn't accept a password argument. So I'm going to have to figure out what to do to really authenticate the user, as opposed to just looking them up.
At this point I have a simple (very simple) Struts 2 application in place and I'm applying Acegi Security to it.
What I've done so far is taken the Acegi Petclinic Tutorial and applied it to my application. I used just about the simplest possible security implementation there -- I changed some names in their default users.properties file and implemented properties-file-driven security.
So far it does work, though -- the login page is exposed to all comers, while the more secure pages deeper in the app are hidden. Routing to the "landing" page upon login works correctly as well.
Next I want to change authentication so that it looks at my users table instead of looking at the properties file. I'll continue to assume just two levels of authorization (anonymous and logged-in user). The Acegi Security reference documentation suggests that I'm going to want to implement the UserDetailsService interface... but of course UserDetailsService doesn't accept a password argument. So I'm going to have to figure out what to do to really authenticate the user, as opposed to just looking them up.
Wednesday, February 27, 2008
Acegi and Struts 2
The easy part is done. Acegi's jar files are in place and they reliably block access to the "protected" part of the application, and redirect users to the login page. Unfortunately I haven't yet figured out how to connect my login action to Acegi authentication.
I believe I will have to have my login action point at my own custom implementation of UserDetailsService, which will in turn have a link to my already-existing UserDao. It will have to put the UserDetails in question into the security context... I think I got it. Now just to, y'know, write the code.
I believe I will have to have my login action point at my own custom implementation of UserDetailsService, which will in turn have a link to my already-existing UserDao. It will have to put the UserDetails in question into the security context... I think I got it. Now just to, y'know, write the code.
Acegi Security
Today I am checking out Acegi Security for our app. I'm slapping it against the application now, early on, rather than trying to shoehorn it in later, after everything works in an insecure fashion.
I would like to know how the hell it's supposed to be pronounced.
It certainly looks cool. Pretty pluggable. Should fit reasonably well within our current application design; I'm just going to write a UserDetailsService implementation that uses our existing Hibernate configuration.
More as I actually do it.
I would like to know how the hell it's supposed to be pronounced.
It certainly looks cool. Pretty pluggable. Should fit reasonably well within our current application design; I'm just going to write a UserDetailsService implementation that uses our existing Hibernate configuration.
More as I actually do it.
Friday, February 22, 2008
Incredibly Basic Design Problem
I'm working on a web application. All noteworthy data in here has been scrubbed appropriately.
This application has users. There are both external and internal users. Each user may have access to a certain subset of the application's functionality, although generally speaking internal users' functionality access is different from external users' functionality access. For instance, we might have an external user who is a customer, and another external user who is a supplier. We might have an internal user who is a sales rep, and another who provides support to the logistics team.
The question I immediately ask myself is this: Am I looking at an inheritance hierarchy, or am I looking at an opportunity for composition?
In other words, do I have:
public abstract class User {...}
public abstract class InternalUser extends User {...}
public class LogisticsUser extends InternalUser {...}
?
Or should I rely instead on composition?
public class User {
Set availableRoles = new HashSet();
}
User fred = new User();
fred.addRole(LOGISTICS);
I might consider answering this question with a look at the database tables that I'm relying on, but (1) I'm more concerned with the conceptual problem here than the implementation details and (2) in this particular case the tables are no help at all anyway.
So here is the core question: Can a user ever fill multiple roles? Java doesn't support multiple concrete inheritance, so a given user either IS a LogisticsUser or he IS a CafeteriaUser or what-have-you. If users can fill multiple roles, then I should be assigning them roles rather than slotting them in a particular concrete class.
And in this particular case, yes, some users do need to fill multiple roles (for instance, we might have a logistics support person who also has administrative authority over some of the website). So I'll be making a simple User hierarchy with a more complex collection of Roles available.
This application has users. There are both external and internal users. Each user may have access to a certain subset of the application's functionality, although generally speaking internal users' functionality access is different from external users' functionality access. For instance, we might have an external user who is a customer, and another external user who is a supplier. We might have an internal user who is a sales rep, and another who provides support to the logistics team.
The question I immediately ask myself is this: Am I looking at an inheritance hierarchy, or am I looking at an opportunity for composition?
In other words, do I have:
public abstract class User {...}
public abstract class InternalUser extends User {...}
public class LogisticsUser extends InternalUser {...}
?
Or should I rely instead on composition?
public class User {
Set availableRoles = new HashSet
}
User fred = new User();
fred.addRole(LOGISTICS);
I might consider answering this question with a look at the database tables that I'm relying on, but (1) I'm more concerned with the conceptual problem here than the implementation details and (2) in this particular case the tables are no help at all anyway.
So here is the core question: Can a user ever fill multiple roles? Java doesn't support multiple concrete inheritance, so a given user either IS a LogisticsUser or he IS a CafeteriaUser or what-have-you. If users can fill multiple roles, then I should be assigning them roles rather than slotting them in a particular concrete class.
And in this particular case, yes, some users do need to fill multiple roles (for instance, we might have a logistics support person who also has administrative authority over some of the website). So I'll be making a simple User hierarchy with a more complex collection of Roles available.
Subscribe to:
Posts (Atom)