I'm quite new to the Spring Security framework, and especially ACLs. After a few hours of reading I think I grasped most of what I need to do to start securing my application.
However something bothers me: while it's very easy to find usage descriptions on how to read the ACL permissions (via #PreAuthorize for example), it starts getting confusing when you want to create and persist them.
The Spring Security manual tells us they don't want to bother with any standard but we are encouraged to use AOP. Many tutorials and answers here rather use the AclService directly inside their business code, destroying the "separation of concerns" principle in the process.
So what should I do ? How do the pros do ? Should I try defining pointcuts on custom annotations for creation/deletion of ACL entries ? Or should I "pollute" my code with ACL concerns ?
Alright so I now understand much better, after one week of work, how these things work.
First, one shall try to stick with the simple, naive way of using ACLs using the AclService directly inside each service layer method. Building an abstraction helps a lot (basically a grantAccess(username, object, permission,...) method in a #Service bean).
Once everything is secured with ACLs writes and #PreAuthorize/#PostAuthorize/#Secured el tests, then you can start thinking about AOP to clean up your code from all the security concerns. You make up a list of service method using ACL writes and you add Advices to them to have one central place where all the security is handled.
Spring Security ACL is extremely easy to set up and understand, even on an existing project with existing users (you'll have to build a migration script).
Related
I've read about how to use Spring in standalone applications but I'm not sure what should be the approach for refactoring a large code base of 120,000 lines for making the change as gradual as possible.
As far as I understand Spring won't inject anything in an object unless that object is managed by the application context. If this is true, I think I have two choices:
1- Start refactoring from the main class down, but this means complicated scenarios will appear soon.
2- Share the application context statically so that I can start refactoring the simplest things, scalating in difficulty when I'm ready.
I'm not a fan of static access so I would try to avoid that choice, but I don't know if it's a good idea to start with the huge classes that are loaded at startup. Any ideas of the best approach?
By the way, is it OK to inject Swing components until I can fix the dependencies?
I think that before approaching such a big technology change, it may be a good idea to start asking yourself if you are following the architecture that Spring guides you to have when you start using it from the beginning.
Therefore, is your application based on the MVC pattern?
If not, maybe your product is not yet ready for being refactored to
use Spring. In this case, I would suggest refactoring the product
design first, so that it complies with the MVC architectural pattern.
If yes, then I would proceed with a use-case-based approach, starting
from the use cases that required a complicated design and
implementation.
E.g. I would look for very important entity classes or business classes containing a lot of logic. This way, you can reduce the risk of doing a lot of refactoring before realizing that, for example, Spring is not a good fit for the core of your product.
After identifying the most critical use case, you can start to experiment how refactoring works on your current product by introducing Spring from end to end on a single critical scenario (user input - business logic - entity manipulation - persistence). If you are successful, then you keep refactoring, otherwise you can go back and try to understand where you need to change your current product before introducing Spring.
Of course, this works when you have some experience with Spring and you do not have to cope with newcomer's issues. If you are new to Spring, then I would recommend getting some experience with Spring before starting the adventure of refactoring such a big project.
Start simply and wire new code/class with spring. You'll amend your existing main method to initialise the ApplicationContext and load your new feature. Over time then as change requests arrive you'll refactor and migrate the existing codebase to use spring dependency injection.
I know there are many security frameworks and "building" a security framework is a bad idea.
In the recent project I have worked on, I used spring security to secure the web application. In the process, I over rided/tweaked some spring security classes to fit my requirement.
My management now wants me to "takeout" the things I did and distribute it as a re usable code in an internal portal.
Now, Is this is a fair thing to ask? I tried to explain them it's just some classes build on spring security and nothing special. But they are insisting on "creating" this framework.
Is this a fair requirement ? Any ideas on how to start ? I understand that getting started with spring security is not very easy.
If I am building this, what are the functions I need to provide?
If they need you to "takeout" the things you did then they should know what they want the framework to do. So Its probably better to ask them for requirements directly.
Regarding:
Is this a fair requirement ?
The answer is probably no. If they want you to do something they should give you specific requirements.
Just Yesterday I asked wheter someone knows a security-library which provides security-apis but at a bit lowerlevl than spring-security. Meaning a library which I call instead of a framework where I have to organize the code according to it (ie using a spring context).
So something I would need are apis for example to create safe remember-me tokens, do basic and dighest authentication, connecting to ldap - or just simply where I could use spring-security but without the spring-container).
After reviewing the AOP pattern, I'm overwhelmed with the ways of how and what to use it for in my spring project.
I'd like to use it as audit log system of all the financial business logic. It just seems to be easy to integrate. But I'd like to hear your take on this.
The question is - what other uses should I consider that are common for this pattern? I would not mind refactoring my current logic to be used with AOP as long as there is benefits to it.
The most common usage is where your application has cross cutting concerns i.e. a piece of logic or code that is going to be written in multiple classes/layers.
And this could vary based on your needs. Some very common examples of these could be:
Transaction Management
Logging
Exception Handling (especially when you may want to have detailed traces or have some plan of recovering from exceptions)
Security aspects
Instrumentation
Hope that helps.
Besides logging/auditing and declarative transaction handling as mentioned by Axel, I would say another usage of AOP is as a request interceptor. For example, let's say you need all requests coming of a server to be intercepted so that you can do something with it (may be to keep track of which app is sending what request to what other app or what database, etc).
The most common use is probably the declarative transaction handling using #Transactional.
Using AOP for audit logging is a perfectly valid use of AOP. You can turn it off for testing and change it as requirements change in production.
The only downside in this case is if you were planning on doing the audit log via SQL. It may be more performant to implement this kind of auditing as triggers directly in the DB.
You can use AOP for your security concerns, for example allow/disallow method access. Another usage of aop is to test your application performance.
It can be used to expose custom metrics (Instrumentation of service) for Alerting and Monitoring of service using client libraries like dropwizard, prometheus.
It helped us, to
Keep this instrumentation code (Not a business logic) outside of actual business logic
Keep these cross-cutting concerns at one single place.
Declaratively apply them wherever required.
For example,
To expose
Total bytes returned by REST AIP - (Can be done in after advice)
Total time taken by REST API i.e server-in and server-out rime- (Can be done using around advice).
As an answer slightly different from what #Axel said, using it to automatically intercept all of your data access calls and apply transactions appropriately is phenomenal. I have mine set up to implement all calls to my dao package that don't start with "get" in a transaction and then anything performed in a method starting with "get" is treated as read only. It's fantastic because aside from the initial setup, I don't have to worry about it, just follow the naming convention.
A while back I wrote an application which used Spring AOP for defining which methods were transactional. I am now having second thoughts as to how much of a great idea this was; I have been hit a few times after a minor refactor (changing method signatures etc), which of course doesn't become apparent until something actually goes wrong (and I have a logically inconsistent database).
So I'm interested in a few things:
Have other people decided to revert to explicit transaction management (e.g. via #Transactional annotations)?
Are there useful tools I can use as part of a build process to help identify whether anything has been "broken"?
If people are using AOP to manage transactions, what steps are they taking to avoid the mistakes I've made?
I'm using IntelliJ IDEA which allows you to browse decorated methods and will refactor Spring XML config together with method name changes, but this is not always sufficient (adding a parameter to a method in the wrong place can affect whether an aspect fires for example)
I am currently using declarative transaction management in the two Java projects I work on, specifying which methods need transactional scope with #Transactional annotation. In my opinion, it is a good mix of flexibility and robustness: you are able to see which methods have transactional behavior via a simple text search, can adjust isolation and propagation attributes by hand if needed, and the additional amount of typing is practically negligent.
On one of those projects, I have security/logging implemented via aspects and have occasionally stumbled on same obstacles you when renaming a method or changing signatures. In the worst case, I lost some logging data of user accessing contracts, and in one release, some user roles were not able to access all application features. Nothing major, but, as far as database transactions go, though, I think it's simply not worth it, and I it is better to type #Transactional bit yourself. Spring does the hard part, anyway.
Regarding (1):
I found #Transactonal a more practical solution in all projects worked on in the past few years. In some very specific cases, however, I had also to use Spring AOP to allow the use of more than one JDBC connection / TransactionManager because #Transaction is tied to a single transaction manager.
Regarding (2):
Having said that, in a mixed scenario, I do a lot of automated testing to find possibly broken code. I use Spring's AbstractTransactionalJUnit4SpringContextTests / AbstractTransactionalTestNGSpringContextTests to create my tests. It's been a very effective solution so far.
I tend to be more of a purist, but I try to keep any and all transaction management beyond a simple autocommit, inside the database itself. Most databases are excellent at handling transaction management, after all, its one of the key components of what a database is meant to do.
I have a concern when it comes to GrantedAuthority objects in a Spring Security application. I'm looking for a good way to handle things. First of all I'm trying to describe my concern, if there are any factual errors do not hesitate to point them out, I'll only be greatful.
Spring Security uses GrantedAuthority instances to act as tokens of authorization in different parts of the application.
By default a GrantedAuthority may present itself as a String. When methods are secured using #Secured("ROLE_NAME"), or URL's are secured using the Spring XML configuration or when the HttpServletRequest request is checked programmatically as in if(request.isUserInRole("ROLE_NAME")) {..} it's always the String that you are using to specify the authority which is checked for.
I'm wondering about the implications of using static strings in several places of the application. If a role name is changed the developer has to hunt down all the old strings and update them. There will be no compile time error if a String is missed, only a problem at runtime.
What is the best way according to you when it comes to handling GrantedAuthority objects in a Spring Security application? What pros and cons does your solution have?
First off, if possible, only do your checks at a particular place in the application (e.g. an HTTP interceptor at the beginning of the request), and using only one of the mentioned approaches. This is a good practice since you will be able to know authoritatively when a user becomes authorized.
If this is not possible, use enums for the role names and only compare on the enums. Therefore, if you wanted to locate all usages in the application it's a simple search.
I do not see a big problem here. It is very unlikely for GrantedAuthority to change the key. Just do not name your roles ROLE_A.
Also, I personally prefer XML security configuration over annotations. In general to keep any related configurations in one place looks like a good idea.
In Spring and other frameworks (especially for dynamic languages) "Convention over Configuration" is used. If you were free to define the role names yourself, you easily find out that much more lines of code are needed.
So stick to the convention. Always use the 3 following roles, ROLE_ANONYMOUS, ROLE_ADMIN, and ROLE_USER. If you need another one, name it accordingly and use it in all occasions. Documentations is important.
Also unit testing is imported. It helps you in the cases that an error isn't caught by the compiler.