|
|
Multiple AuthenticationProcessingFilterEntryPoint ?
Hi all. I'm very new to Acegi, and I have problems for which I don't see a solution.
I have to build an online travel agency website. For this website, there are two types of users: customers and employees.
Customers have to be able to register, log in and out, and book a trip.
Employees have some CRUD-responsibilities, along with some more advanced stuff.
Actually there is a third type of user, because even when you're not logged in, you can do certain stuff. But I wasn't planning to make this secure.Now, I implemented acegi (via a DaoAuthenticationProvider and a class implementing UserDetailsService) for the employee part, and this works allright. If a non-logged in employee tries to access a page he isn't qualified for, he's redirected to a login page, login works, ...The problem is that customers and employees are in different data tables (using a MySQL database), so I figured to write another class implementing UserDetailsService, another AuthenticationProcessingFilter, etc.
This is not working. When I go to the secured part for the employee, things still work as they should. But when I go to the secured part for the customer, it just shows the page without restrictions. When I strip out the employee part out of the applicationContext, the customer part does indeed work as planned.If anyone has an idea as to how to implement this best, I would be grateful. Also, i figure it's best to not post the entire code, because this post would be very long. I'll be happy though to post some code if anyone asks for this.
Thanks in advance.
So your basic problem is that there are two different tables containing the user information. You basically want to check both. That should be fairly simple.
You could either do this in your UserDetailsService check both and if they aren't found in either throw an exception. An alternative way would be to configure multiple authentication providers. Both would be DaoAuthenticationProviders but they would have different UserDetailsService injected. That way Acegi would check both for a valid login.
First of all, thanks for the fast reply.Originally Posted by karldmooreSo your basic problem is that there are two different tables containing the user information. You basically want to check both. That should be fairly simple.
You could either do this in your UserDetailsService check both and if they aren't found in either throw an exception.
Well, one UserDetailsService isn't really an option, I think. I never want to check on both tables during one login attempt. Because of the (not so fantastic, but I didn't make it) database-design, it's possible that there is a customer with the same user ID and password as an employee. [next part comes after your next quote]
An alternative way would be to configure multiple authentication providers. Both would be DaoAuthenticationProviders but they would have different UserDetailsService injected. That way Acegi would check both for a valid login.
So, because of the above, I indeed created two UserDetailsServices (that each check one database, depending on the login form - I got the 2 different login forms working just fine) and injected these in two DaoAuthenticationProvider.
Now, because I have two DaoAuthenticationProviders, I have created two ProviderManagers with these injected. And so, also two FilterSecurityInterceptors.
Basically, I doubled just about everything, but it just won't work like I expected.
I have attached the acegi part of my applicationContext. I hope you can find your way in it to see what's wrong...
Note that I also have two DispatcherServlets, one for the /front (customer) part and one for the /back (employee) part.
You don't need to double everything. You can set multiple AuthenticationProviders on a single provider manager. I would have thought this would be the best way to do it. If you configured something like remember me authentication as well you would simply add it as another AuthenticationProvider.
This is the code for the example that ships with Acegi. It has mulitple providers, can't you just treat your two DaoAuthenticationProviders in the same way?
Code:
lt;bean id=quot;authenticationManagerquot; class=quot;org.acegisecurity.providers.ProviderManagerquot;gt;
lt;property name=quot;providersquot;gt;
lt;listgt;
lt;ref local=quot;daoAuthenticationProviderquot;/gt;
lt;bean class=quot;org.acegisecurity.providers.anonymous.AnonymousAuthenticationProviderquot;gt;
lt;property name=quot;keyquot; value=quot;changeThisquot;/gt;
lt;/beangt;
lt;bean class=quot;org.acegisecurity.providers.rememberme.RememberMeAuthenticationProviderquot;gt;
lt;property name=quot;keyquot; value=quot;changeThisquot;/gt;
lt;/beangt;
lt;/listgt;
lt;/propertygt;
lt;/beangt;
As your saying a customer and employee could have the same userId, you would need to do something to tell them apart. I would have thought the best way to do this is override the filter and extend the token. You can then add something to the token to say what type it is. This also means that in you can check this in your user service.
Originally Posted by karldmooreYou don't need to double everything. You can set multiple AuthenticationProviders on a single provider manager. I would have thought this would be the best way to do it. If you configured something like remember me authentication as well you would simply add it as another AuthenticationProvider.
This is the code for the example that ships with Acegi. It has mulitple providers, can't you just treat your two DaoAuthenticationProviders in the same way?
Ah yes, I should have seen this. I have just made this change to the applicationContext.
Am I correct in thinking that I still need to have two ExceptionTranslationFilters (for directing to a different quot;not authorizedquot;-page) and two AuthenticationProcessingFilters (for directing to different authentication failure and success pages)?
However, changing this didn't solve the problem, I get weird results. When I go to /front/home (which is secured), I get to see /front/login (which is expected).
But when I go to /back/home (also secured), I also get to see /front/login. I don't see why.
edit: if I go to secured /back/home, I get to see /front/login. If I try to login with a valid user/pass for the back part, I get sent to the /back/home. But, if I type a user/pass for the front part in this page, I get sent to /front/noauth (and that should be /back/noauth)
I don't see why you need two of anything apart from the DaoAuthenticationProvider and UserDetailsService. Wouldn't it be possible to have the same page for everyone and simply have a hidden field containing the type. So you go to different ucls which forward to the same page telling it where they have come from. This means you only configure everything once, you just need to ensure you pull the value out in the filter and set it on the token.
e.g.
Code:
/user/login uses page login.jsp sets hidden value to user submits to /j_acegi_security_check filter gets value out of session sets on token
/employee/login uses page login.jsp sets hidden value to employee submits to /j_acegi_security_check filter gets value out of session sets on tokenSeems like a good way of handling this problem, yes.
As for this specific construction, would you have any clue as to why this isn't working? I will implement it your way, but I would still like to understand why my solution isn't behaving the way I had expected.
Its difficult to see why its not working without me have a play with the application and have a detailed look at the configuration. I'd have a go with the changes and spend sometime understanding what is going on. If you have problems with this post back. Good luck!
Allright, thanks for the help so far!
New working day, time to make this whole thing work, but I think I need a little more help here (like I said, I'm really new to all this...).Originally Posted by karldmooree.g.
Code:
/user/login uses page login.jsp sets hidden value to user submits to /j_acegi_security_check filter gets value out of session sets on token
/employee/login uses page login.jsp sets hidden value to employee submits to /j_acegi_security_check filter gets value out of session sets on tokenI see the big picture, but I'm having trouble with the details.
My main problems for now are:
1) When I want to go to a protected part (say, I type the protected quot;/user/homequot;), how can I set the hidden value in the login.jsp ?
It seems easy to do it when I go to the login page via a direct ucl (because then it will pass through a controller, making it easy to set something in the modelandview), but how to do it when I go through the authentication chain?
2) I see how to extend the token, but the quot;override the filterquot; part isn't entirely clear. What exactly (which filter, which method(s)) do you mean by this? |
|