I've spent all day Googling and looking at various questions on here, trying to come up with the best solution for implementing authentication and authorization. I've come up with part of the solution now, but am hoping someone can fill in the gaps. I realise there is a lot of text below, but please bear with me :O)
Background
I have inherited a part completed CRM application which currently uses JSF 2.0, JavaEE 6, JPA and a PostgreSQL database. Unfortunately, the guys who originally started building this web app in their infinite wisdom decided that it would be best to leave authentication/authorization to the end - I've now got to put it in.
The application is essentially split into three layers - the views, the managed beans and the DAO's. This means that the managed beans are particularly 'fat' since they contain all of the business logic, validation and navigation logic.
Authentication/Authorization requirements
Forms based authentication, validating against credentials stored in the PostgreSQL database.
The only page that will be publicly accessible (by anonymous users) will be the login page.
I need to prevent access to certain areas of the application based on a users role. For example, only users with the 'Admin' role should be able to access the create/edit user page.
I also need to be able to restrict access to certain area's of a page. For example, a user with the 'Sales Rep' role should be able to view a customers details, but the save/edit button should only be displayed if the user has the 'Customer Service' role.
Where I'm at
The first thing I plan on doing is to follow this User Authentication and Authorization using JAAS and Servlet 3.0 Login example. This I believe will fulfil my first 3 requirements.
In order to show/hide save buttons etc on pages, I can use the technique described in this SO answer. This will partly solve requirement 4, however I think that I still need to secure the action methods and or the managed beans themselves. For example, I would like to be able to add an annotation or something to the save() method on the customer bean to ensure that only users with the 'Customer Service' role can call it - this is where I begin to run into issues.
I guess one option would be to do something similar to what I am proposing to do in the view and use facesContext to check if the current user "is in role". I'm not keen on this as it will just clutter up my code and would rather use annotations instead. If I did go down this route however, how would I return a http 403 status?
The javax.annotation.security.* annotations seem to be a good fit for declaritively defininig access to areas of the application, however as far as I understand, they can only be added to EJB's. This would mean that I would need to move all of my business logic out of the managed beans where it currently resides to new EJB's. I think this would have the added benefit of separating the business logic out into it's own set of classes (delegates, services or whatever you chooses to call them). This would be quite a large refactor however which isn't going to be aided by a lack of unit test or integration tests. I'm not sure whether the responsibility of access control should be at this new service level either - I think it should be on the managed beans.
Other alternatives
During my research I have found lots of people mentioning frameworks such as Spring and Seam. I have some limited experience with Seam, I think it would have been a good fit for this project and from what I recall I believe it solves the authorization issues I am having, but I think it is too late in the day to introduce it now.
I have also seen Shiro mentioned in various places. Having looked at the 10 minute tutorial this seemed like a good fit, especially in conjunction with Deluan Quintao's taglib but I have been unable to find any tutorials or examples of how to integrate it with a JSF web app.
The other alternative I have come across surprisingly regularly is implementing a custom solution - this seems crazy to me!
Summary
In summary then, I'd really like some guidance on whether I'm heading down the right path in terms of implementing authentication and authorization and how I fill in that missing piece of securing individual methods and/or managed beans (or at least the code they delegate to) and/or how I can manually return a HTTP Status 403.
Have you tried anything with Spring Security - Latest being version 3
http://janistoolbox.typepad.com/blog/2010/03/j2ee-security-java-serverfaces-jsf-spring-security.html
http://ocpsoft.org/java/jsf-java/spring-security-what-happens-after-you-log-in/
rather than using a request filter or using JAAS, spring security is a comprehensive security framework that will resolve most of your security concerns .
You can use it to authenticate a user using a db realm, authorize him and redirect as necessary based on the provided authentication information.
you can secure the methods that you have written
http://blog.solidcraft.eu/2011/03/spring-security-by-example-securing.html
#PreAuthorize("hasRole('ROLE_XXX')") is the way
to make certain elements of a page secure..
//content
more reading and examples
http://static.springsource.org/spring-security/site/petclinic-tutorial.html
After carrying out a lot of research I have come to the conclusion that firstly the requirements of my application would benefit from being deployed to an application server that fully implements the Java EE specification, rather than a servlet container like Tomcat. As the project I am working on uses Maven, the key thing here was getting the dependencies set up correctly - this wasn't easy and took a fair bit of googling and trial and error: I'm sure there is a more scientific approach that could be taken.
I then had to create a mysql module to get my application to talk to the database properly and then remove the factory that had been implemented to create DAO's and convert them to EJB's instead. I also had to update hibernate.cfg.xml to reference the datasource I added and persistence.xml to set the transaction type to JTA and also reference the JTA data source. The only other complication was that the Open Session In View pattern was being used which meant I ended up with hibernate lazy initialization errors when entities were accessed in the views. I reimplemented the filter as shown at the bottom of this answer, to get around this. I see this as a temporary measure to get things working again before I can hopefully refactor this area and remove the need for the filter.
Moving to JBoss took just over a day and I'm sure it could have been done much quicker if I was more experienced with Java EE and Maven. Now that I'm at that point I'm in a good position to be able to drop seam 3 security into the project and utilise that, rather than trying to hack together a solution which is essentially the direction I was going to take. The nice thing about Seam 3 is that you can to a certain extent pick and choose which modules you use rather than having to add the entire framework (like Seam 2). I think a number of the other modules are going to be helpful as well however and will help me amongst other things get rid of the open session in view pattern.
One thing that did concern me with using Seam was that I was told about DeltaSpike. This seems as though it will probably replace seam and there are no plans for any more versions of seam. I have decided that since seam is still being supported and if DeltaSpike takes as long to come to fruition as seam 3, then it is pretty safe to use seam 3.
I will hopefully get round to writing a proper blog post describing this migration in proper detail.
public class OSVRequestFilter implements Filter {
private static final String UserTransaction = "java:comp/UserTransaction";
private static Logger logger = LoggerFactory.getLogger(EntityManagerRequestFilter.class);
public void init(FilterConfig config) throws ServletException {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
if (request instanceof HttpServletRequest) {
doFilter(request, response, chain, getUserTransaction());
}
}
private UserTransaction getUserTransaction() throws ServletException {
try {
Context ctx = new InitialContext();
return (UserTransaction)PortableRemoteObject.narrow(ctx.lookup(UserTransaction), UserTransaction.class);
}
catch (NamingException ex) {
logger.error("Failed to get " + UserTransaction, ex);
throw new ServletException(ex);
}
}
private void doFilter(ServletRequest request, ServletResponse response, FilterChain chain, UserTransaction utx) throws IOException, ServletException {
try {
utx.begin();
chain.doFilter(request, response);
if (utx.getStatus() == Status.STATUS_ACTIVE)
utx.commit();
else
utx.rollback();
}
catch (ServletException ex) {
onError(utx);
throw ex;
}
catch (IOException ex) {
onError(utx);
throw ex;
}
catch (RuntimeException ex) {
onError(utx);
throw ex;
}
catch (Throwable ex){
onError(utx);
throw new ServletException(ex);
}
}
private void onError(UserTransaction utx) throws IOException, ServletException {
try {
if ((utx != null) && (utx.getStatus() == Status.STATUS_ACTIVE))
utx.rollback();
}
catch (Throwable e1) {
logger.error("Cannot rollback transaction", e1);
}
}
public void destroy() {
}
}
Related
So I'm working on implementing Oath2 authentication to allow my app to access Intuit Quickbooks company resources (items, customers, etc).
Intuit provides working examples using Spring, but I'm developing my app using JavaEE 8 with GlassFish5.
The Spring sample app callback contoller is structured as follows:
#Controller
public class CallbackController {
...
#RequestMapping("/oauth2redirect")
public String callBackFromOAuth(#RequestParam("code") String authCode, #RequestParam("state") String state, #RequestParam(value = "realmId", required = false) String realmId, HttpSession session) {
...
//after successful validation
return "connected";
This is the redirect handler controller; which address it's configured at the intuit portal (in this case, http://localhost:8080/oauth2redirect) that will be called after user approves the app and intuit will send back authorization code to this url.
So I'm a bit stuck finding what's the equivalent Spring callback redirect handler in JavaEE.
Is a #WebServlet or #WebService needed here? But then it wouldn't integrate nicely with JSF to just return the "connected" string so that it redirects to desired page (in this case connected.xhtml).
Not looking for workarounds, but the correct and standard way of implementing this on JavaEE. If you can point me to some sample apps out there or tutorials I would greatly appreciate it.
Thanks a lot in advance!
Here's full source code for callback handler controller and the full sample app.
There is at least not a really good alternative in JSF. Yes, you could 'abuse' JSF but there are other, better standards for this and this is (almost) what Spring also does. If you read the Spring Specs , you'll see the word 'Rest' being used a lot.
Well, there is a real java standard called 'Jax-RS' that is the standardized counterpart of what you do in spring.
This provides a decent analysis of the two So Jax-RS is the way to go.
But a #WebServlet or #WebService integrate perfectly with JSF. You can store any authentication information in the session and use that from JSF. No problem at all.
With Liferay 6, using *LocalServiceUtil static calls was common. Starting from Liferay 7, these calls should be avoided in favor of #Referenceing the OSGi service and using it as a private member of the class, if I understood correctly (feel free to correct me).
Problem: When I replace my old *LocalServiceUtil calls with the OSGi-friendly equivalent, I get this exception:
com.liferay.portal.kernel.security.auth.PrincipalException:
PermissionChecker not initialized
at com.liferay.portal.kernel.service.BaseServiceImpl.getPermissionChecker
at com.liferay.portal.service.impl.UserServiceImpl.getUserById
How to fix it?
I could get a random admin via the OSGi equivalent of UserLocalServiceUtil.getRoleUsers(RoleLocalServiceUtil.getRole(company.getCompanyId(),"Administrator").getRoleId()) and use it in the the OSGi equivalent of PermissionThreadLocal.setPermissionChecker(PermissionCheckerFactoryUtil.create(randomAdmin)) but that sounds very hacky, plus it would put the responsibility of my code's actions on the shoulders of this unlucky admin.
My code:
protected void myMethod() {
userService.getUserById(userId);
}
#Reference(unbind = "-")
protected com.liferay.portal.kernel.service.UserService userService;
I think you actually wanted to inject UserLocalService.
In OSGi you should only strip the *Util suffix to receive equivalent functionality.
What you did is moved from LocalService (UserLocalServiceUtil) to remote service (UserService). The local services do not check permissions so there is no permission checker initialisation.
Apart from the above, you should be sure that no mischief can happen when using Local services. It's not recommended to expose this kind of functionality to end users but it's fine for some background processing.
I am using Mvvmcross crosscore in my project
I am trying to bind my loginviewmodel to the loginviewcontroller
I bound a command for the login button. the app waits until it gets a login response, which is stored in the loginViewModel itself..
How can I communicate this to the loginviewcontroller --- regarding the login status and login error message if any
Can I access the viewmodel datacontext inside my loginviewcontroller ??? and how ?
What is the best approach to communication any items in the viewmodel back ( I basically mean all the NON-UI binding items)
I am using Mvvmcross crosscore in my project
I'm assuming from this that you followed the CrossLight sample N=39.
Can I access the viewmodel datacontext inside my loginviewcontroller ??? and how ?
If you followed N=39. then you can access the DataContext using the property called DataContext - see https://github.com/MvvmCross/NPlus1DaysOfMvvmCross/blob/master/N-39-CrossLight-Touch/CrossLightTouch/MyViewController.cs#L33
public object DataContext
{
get { return BindingContext.DataContext; }
set { BindingContext.DataContext = value; }
}
Beyond this, there are many other examples in the N+1 videos which demonstrate how to communicate between ViewModels and Views including error messages and loading dialogs - e.g. N=34 shows one implementation of progress dialogs - https://github.com/MvvmCross/NPlus1DaysOfMvvmCross/tree/master/N-34-Progress
A complete index of N+1 videos is available on http://mvvmcross.wordpress.com
Obviously not all of these are appropriate for your CrossLight approach to development, but this is where you can allow your custom mvvm approach to fill the gap - it's code for you to write in your custom framework.
One of the best methods solving viewmodel interdependencies is using a loosely coupled approch using the MessageBus/Event Aggregator pattern. There's a plugin for MvvmCross. Or you could use the excellent TinyMessenger.
In principle when using this approach, you no longer establish hard references between the publisher and consumers of arbitrary notifications. Instead notifications get published on a message bus and every one is free to listen and subscribe.
I am designing a system using domain driven design concepts and I am struggling with a few things. The "domain" is essentially a business system for the company I work for. I am also using dependency injection. So, in my model I have things related to any typical business system (Employee, Order, Invoice, Deposit, etc..). Right now I am trying to create a cash posting application in which users (aka Employees) can create deposits and apply them to unpaid invoices. The problem that I am having is that we are also using an external business system (Microsoft Dynamics Nav) to handle our accounting transactions. So essentially I am dealing with two different databases. So, for the cash posting application I have modeled the domain objects Deposit and DepositLine. I also have in my domain an IDepositRepository interface that is responsible for persisting the deposits. To get a deposit from the system I just want to grab it directly from the database. However, in order to create a deposit I have to use the Dynamics Nav web services because there is certain logic that gets executed behind the scenes that I don't know about. I started looking at the concept of an Anti Corruption layer in which I could translate my version of the deposit object into a deposit object suitable for the web service. So here is what I am envisioning right now:
Domain Layer
- Models
- Deposit
- DepositLine
- Repositories
- IDepositRepository
Infrastructure Layer
- Data
- Repositories
- DepositRepository
- DynamicsNav
- Services
- INavCashManagementService
- Translators
- IDepositTranslator
- Adapters
- INavAdapter
Now I thought i might implement the DepositRepository like so:
public class DepositRepository
{
private INavCashManagementService navCashManagementService;
public DepositRepository(INavCashManagementService navCashManagementService)
{
this.navCashManagementService = navCashManagementService;
}
public Deposit GetDeposit(int id)
{
// use nhibernate to get directly from the database
}
public void SaveDeposit(Deposit deposit)
{
this.navCashManagementService.CreateDeposit(deposit);
}
}
First of all, is this an appropriate design? My next problem is that users are also going to have to "Post" deposits. The Nav web services will also have to be used to run the posting routine. But, this is more of a business process rather than a persistence issue, so I don't see it fitting into the repository. So I am wondering how/where I should call the posting routine. Should I create a domain service like this:
public class CashPostingDomainService
{
private INavCashManagementService navCashManagementService;
public CashPostingDomainService(INavCashManagementService navCashManagementService)
{
this.navCashManagementService = navCashManagementService;
}
public void PostDeposits()
{
this.navCashManagementService.PostDeposits();
}
}
One confusion I have with domain driven design is external dependencies. Doesn't the CashPostingDomainService class now have an external dependency on Nav? I know the implementation isn't in the domain layer, but doesn't the interface itself make it a dependency? The same goes with other technical concerns like sending emails. If I have an IEmailService interface and want to send an email once the deposits are posted, would I inject the interface into the CashPostingDomainService class? Or would that be part of the application workflow? So which one of these options make the most sense (if any):
1
public class DepositController
{
private ICashPostingDomainService cashPostingDomainService;
private IEmailService emailService;
public DepositController(
ICashPostingDomainService cashPostingDomainService,
IEmailService emailService)
{
this.cashPostingDomainService = cashPostingDomainService;
this.emailService = emailService;
}
public void PostDeposits()
{
this.cashPostingDomainService.PostDeposits();
this.emailService.NotifyDepositsPosted();
}
}
2
public class DepositController
{
private ICashPostingDomainService cashPostingDomainService;
public DepositController(
ICashPostingDomainService cashPostingDomainService)
{
this.cashPostingDomainService = cashPostingDomainService;
}
public void PostDeposits()
{
this.cashPostingDomainService.PostDeposits();
}
}
public class CashPostingDomainService
{
private INavCashManagementService navCashManagementService;
private IEmailService emailService;
public CashPostingDomainService(
INavCashManagementService navCashManagementService,
IEmailService emailService)
{
this.navCashManagementService = navCashManagementService;
this.emailService = emailService;
}
public void PostDeposits()
{
this.navCashManagementService.PostDeposits();
this.emailService.NotifyDepositsPosted();
}
}
Thanks for the help!
is this an appropriate design?
It seems fine to me. The important thing is for your Repository to stay oblivious of the Nav side of things and let the anticorruption layer handle that. You might want to have a look here for a similar example.
I know the implementation isn't in the domain layer, but doesn't the
interface itself make it a dependency?
You may have that feeling because the name of your (supposedly agnostic) service interface contains "Nav". To reflect a service abstraction that could have Nav or any other ERP as an implementation, you should rename it to ICashManagementService.
If I have an IEmailService interface and want to send an email once
the deposits are posted, would I inject the interface into the
CashPostingDomainService class? Or would that be part of the
application workflow?
It's your architectural decision to choose one or the other.
Option 1. means that sending an email is an intrinsic part of the deposit posting domain operation. If you take your domain module and reuse it in another application, posting deposits will automatically result in sending an email whatever that application is about. This might be the right thing to do in your context, or you might want to make things a little more generic (like, sending feedback after the operation but not deciding in the domain service whether this feedback should be mail, a log file, etc.)
Option 2. means that the sequence of events that happen after posting the deposits is application specific, that is at the use case level rather than business/domain level. It is up to the Controller (or Application Service) to decide which actions to take -send an email or anything else. Consequently, different applications based around your domain layer could decide to take different actions. This also means possible code duplication between these applications if several of them chose to send mails.
I am looking for ways to restrict certain actions in Controller(s) based on whether the user is logged in or not. I looked at the Security interceptor but how would the Security controller code know which action is being executed and what is its required access level?
I am looking for something like:
#Auth-level("logged-in")
public static Member getProfile()
{
.....
}
#Auth-level("cookied")
public static void browseCatalog()
{
.....
}
#Auth-level("anonymous")
public static void contactUs()
{
.....
}
Is this possible in Play? Or is there a similar solution for the problem above?
The way I did this in my Struts application was to use XDoclet to create a mapping from my Action classes comments and using a Servlet filter to examine the request and figure out if access is allowed or not. I was hoping for an easier way to do this in Play!
Thanks!
Take a look at the following documentation for the secure module as an example of an action/controller interceptor...
http://www.playframework.org/documentation/1.1/secure
Pay particular notice of the #Check notation, which gives you what you are asking for.