I started working on an existing spring boot application with spring security.
We have our resources authorized using with the #PreAuthorize annotation
I now have a new use case where I need to apply authorization when updating a collection within the resource
I mean. The logged in user may have permissions to update an entity, but he may not have access to update a collection within the entity
I read that enabling global method security I can put the authorization annotation on any method, so I tried putting it on a method that does the collection update. But it didn't work
Can I really use this annotation anywhere or should it be used only on controller bound methods?
I guess the question is whether this annotation is processed as a filter on a request or is it AOP?
I use it as follows:
#Value
private class FooDto {
int id;
String property1;
Collection<Bar> bars;
}
#PreAuthorize("#id, 'FOO_RESOURCE:WRITE'")
public FooDto update(int id, FooDto dto) {
Foo foo = fooRepository.findBy(id);
updateBars(dto.getBars(), foo.getBars());
return updatedEntityDto;
}
#PreAuthorize("#id, 'BARS:WRITE'")
private void updateBars(Collection<Bar> dtoBars, Collection<Bar> entityBars) {
// update the collection
}
Related
I am trying to dive deep into the mechanics of the Spring Framework. The following piece of code achieves inserting "token" parameter from HTTP request into the token variable:
#POST
#Path("/")
Response saveOne(#HeaderParam("token") String token, UserDTO uDTO) {
}
How can I achieve the same?
And what tools do I need? Is it done using AOP? Say, I would like to come up with a custom annotation #MyAnnotation and any parameter or field marked by it would be customized by some logic. Example:
public class MyClass {
...
#MyAnnotation
private String myVar1;
public void myMethod(#MyAnnotation myParam1) {
...
}
...
}
When I create instance of MyClass or when I autowire it in my Spring application I would like to have a piece code that triggers right before I use the myVar1 variable and/or when I call the myMethod(param1). I want to set the annotated variable to whatever value I want. How can I do this?
What makes me wonder is how Spring does do it in case of the #HeaderParam? I basically need the same functionality.
I basically understand the functions of #DeclareRoles and #RolesAllowed, but I'm not sure where to add the #DeclareRoles correctly. I testet with a vaadin application with ejb session beans and cdi in glassfish 4. The application is packed as war not as ear.
#DeclareRoles on no class:
Obviously nothing works. HttpServletRequest.isUserInRole() and SessionContext.isCallerInRole() are always returning false. #RolesAllowed always denies access.
#DeclareRoles on the Servlet:
#RolesAllowed and HttpServletRequest.isUserInRole() are working as expected. SessionContext.isCallerInRole() is always returning false.
#DeclareRoles on a session bean:
#RolesAllowed, HttpServletRequest.isUserInRole() and SessionContext.isCallerInRole() are working as expected. Even if SessionContext.isCallerInRole() is called in a different session bean than the one with #DeclareRoles
My question now are:
Where is the right place to put #DeclareRoles?
Is it ok to set it only once or should it annotate every bean that uses SessionContext.isCallerInRole() or #RolesAllowed?
Method permissions can be specified on the class, the business methods of the class, or both. Method permissions can be specified on a method of the bean class to override the method permissions value specified on the entire bean class. The following annotations are used to specify method permissions:
#DeclareRoles: Specifies all the roles that the application will use, including roles not specifically named in a #RolesAllowed annotation. The set of security roles the application uses is the total of the security roles defined in the #DeclareRoles and #RolesAllowed annotations.
The #DeclareRoles annotation is specified on a bean class, where it serves to declare roles that can be tested (for example, by calling isCallerInRole) from within the methods of the annotated class. When declaring the name of a role used as a parameter to the isCallerInRole(String roleName) method, the declared name must be the same as the parameter value.
The following example code demonstrates the use of the #DeclareRoles annotation:
#DeclareRoles("BusinessAdmin")
public class Calculator {
...
}
The syntax for declaring more than one role is as shown in the following example:
#DeclareRoles({"Administrator", "Manager", "Employee"})
#RolesAllowed("list-of-roles"): Specifies the security roles permitted to access methods in an application. This annotation can be specified on a class or on one or more methods. When specified at the class level, the annotation applies to all methods in the class. When specified on a method, the annotation applies to that method only and overrides any values specified at the class level.
To specify that no roles are authorized to access methods in an application, use the #DenyAll annotation. To specify that a user in any role is authorized to access the application, use the #PermitAll annotation.
When used in conjunction with the #DeclareRoles annotation, the combined set of security roles is used by the application.
The following example code demonstrates the use of the #RolesAllowed annotation:
#DeclareRoles({"Administrator", "Manager", "Employee"})
public class Calculator {
#RolesAllowed("Administrator")
public void setNewRate(int rate) {
...
}
}
#PermitAll: Specifies that all security roles are permitted to execute the specified method or methods. The user is not checked against a database to ensure that he or she is authorized to access this application.
This annotation can be specified on a class or on one or more methods. Specifying this annotation on the class means that it applies to all methods of the class. Specifying it at the method level means that it applies to only that method.
The following example code demonstrates the use of the #PermitAll annotation:
import javax.annotation.security.*;
#RolesAllowed("RestrictedUsers")
public class Calculator {
#RolesAllowed("Administrator")
public void setNewRate(int rate) {
//...
}
#PermitAll
public long convertCurrency(long amount) {
//...
}
}
#DenyAll: Specifies that no security roles are permitted to execute the specified method or methods. This means that these methods are excluded from execution in the Java EE container.
The following example code demonstrates the use of the #DenyAll annotation:
import javax.annotation.security.*;
#RolesAllowed("Users")
public class Calculator {
#RolesAllowed("Administrator")
public void setNewRate(int rate) {
//...
}
#DenyAll
public long convertCurrency(long amount) {
//...
}
}
The following code snippet demonstrates the use of the #DeclareRoles annotation with the isCallerInRole method. In this example, the #DeclareRoles annotation declares a role that the enterprise bean PayrollBean uses to make the security check by using isCallerInRole("payroll") to verify that the caller is authorized to change salary data:
#DeclareRoles("payroll")
#Stateless
public class PayrollBean implements Payroll {
#Resource SessionContext ctx;
public void updateEmployeeInfo(EmplInfo info) {
oldInfo = ... read from database;
// The salary field can be changed only by callers
// who have the security role "payroll"
Principal callerPrincipal = ctx.getCallerPrincipal();
if (info.salary != oldInfo.salary && !ctx.isCallerInRole("payroll")) {
throw new SecurityException(...);
}
...
}
...
}
The following example code illustrates the use of the #RolesAllowed annotation:
#RolesAllowed("admin")
public class SomeClass {
public void aMethod () {...}
public void bMethod () {...}
...
}
#Stateless
public class MyBean extends SomeClass implements A {
#RolesAllowed("HR")
public void aMethod () {...}
public void cMethod () {...}
...
}
More information:
Securing Enterprise Beans
I'm using HK2 as part of a Jersey RESTful API. I'm working in an multitenant system, and in most of my API calls, the tenant is a path parameter. I also have several DAOs, which currently accept the tenantId in their constructor, such as:
public final class WidgetMapper {
public WidgetMapper(final int tenantId) { .. }
..
}
I'd like to use HK2 to provide my DAOs to the other layers of my application. What's the right way to do this?
Change the DAOs to use a setter rather than a constructor argument. Only .. ick. The tenantId is part of the required state of the DAO.
Add a layer of abstraction. Create <interface>MapperFactory and MapperFactoryImpl, which has a no-arg constructor and a bunch of getters, such as getWidgetMapper and getGizmoMapper. Only .. this seems cumbersome. I'd rather not have to maintain these extra classes.
Is there some magic way for HK2 to inject that int value into the WidgetMapper constructor at runtime? Then I could inject the tenantId into the mapper, and the mapper into my other classes.
?? Other HK2 magic?
You need to extract the tenant ID from the path parameter in the request, so as long as it's OK to instantiate your DAOs for each request, you can implement a Factory.
public WidgetMapperFactory implements Factory<WidgetMapper> {
private final ContainerRequestContext containerRequestContext;
#Inject
public WidgetMapperFactory(ContainerRequestContext containerRequestContext) {
this.containerRequestContext = containerRequestContext;
}
public WidgetMapper provide() {
UriInfo uriInfo = containerRequestContext.getUriInfo();
List<String> matchedUris = uriInfo.getMatchedURIs();
int tenantId = 1; // Actually work it out from the matched URIs
return new WidgetMapper(tenantId);
}
public void dispose() {
// Do any clean up you need
}
}
Then bind the factory:
public MyResourceConfig extends ResourceConfig {
public MyResourceConfig() {
register(new AbstractBinder() {
#Override
protected void configure() {
bindFactory(WidgetMapperFactory.class).to(WidgetMapper.class).in(RequestScoped.class);
}
});
}
}
You can then inject WidgetMapper in a Resource class, and the WidgetMapper doesn't have any knowledge it's being used in a web service.
Change the DAOs to use a setter rather than a constructor argument.
Only .. ick. The tenantId is part of the required state of the DAO.
If your DAOs are singletons I don't see how this would work (or at least how it could be done cleanly).
What's the right way to do this?
IMO, I think the best approach is to have 1) singleton DAOs 2) some type of proxy that got injected into the DAOs when they were instantiated by HK2 and then provided the correct tenant id for the current thread.
I can think of two ways to do this:
Option 1:
I haven't tried it, but I think you could probably inject UriInfo into your DAOs, either through the constructor, a private field, or setter. You could extract the tenant id for the current request from the UriInfo instance.
If I were you, I'd create an abstract class for my DAOs that got a UriInfo injected into a private field. I'd then provide a protected method to return the current tenant id from uriInfo.getPathParameters
public abstract class AbstractDao {
// jersey/hk2 provides a proxy that references the current thread-bound request
#Context
private UriInfo info;
protected int getTenantId()
{
// always returns the tenant id for the current request. TODO: add
// logic to handle calls that don't have a tenant id.
return Integer.valueOf(info.getPathParameters.getFirst("tenantId");
}
}
Option 2:
?? Other HK2 magic?
You could write a custom injection resolver.
One more idea...
Option 3:
This one doesn't directly answer your question since it doesn't use HK2 to inject the tenant ID into the DAOs but I think it's worth mentioning.
You could implement your own ContainerRequestFilter that obtained the tenant id and provided it to other components in your app.
By default, Jersey will invoke the filter after it resolves the resource method but before the method is actually invoked. You can obtain a UriInfo from the ContainerRequestContext, get the tenant id path param, then stuff that param into your own thread local variable. You could then reference the thread local within your DAO. Again, I recommend adding a protected method in a base DAO class to encapsulate this logic.
in most of my API calls, the tenant is a path parameter
Optionally, you can use NameBinding to control the behavior described above.
If you wanted to, you could implement option 3 using a regular ServletFilter instead.
Note:
After I wrote this answer, I realized that I assumed you were comfortable extending ResourceConfig, that you knew how to obtain an instance of ServiceLocator, and that you were comfortable with adding your own bindings. If you're not, let me know and I'll edit my answer to provide more details.
I'm looking to see whether or not the following is even possible, as all preliminary searches haven't turned back anything to indicate either way.
I'd like to use Hibernate's Validator annotations to validate bean methods, and I would like to use some AOP framework (Spring, AOP Alliance, AspectJ, etc.) to intercept methods annotated with a subset of the Hibernate Validator annotations (#NotNull, #NotEmpty, #Email, etc.); I then want AOP advice to run when they are encountered.
Is this possible to do? If so, I am having a tough time visualizing how the code would work. Using Spring AOP's MethodInterceptor interface as an example:
First, the bean using Hibernate Validator:
public class SomeBean
{
private String data;
// Hibernate Validator annotation specifying that "data" cannot be an empty
// string.
#NotEmpty
public String getData() { ... } // etc.
}
Then, some code using that bean:
public void someMethod()
{
SomeBean oBean = new SomeBean();
// Validation should fail because we specified that "data" cannot be empty.
oBean.setData("");
}
Next, the AOP advice to be ran when Hibernate Validator-annotated methods are encountered.
public class ValidationInterceptor implements MethodInterceptor
{
public Object invoke(MethodInvocation invocation)
{
// Here's where we would use Hibernate's validator classes.
// My code example here is wrong, but it gets the point across.
Class targetClass = invocation.getClass(); // Should give me SomeBean.class
ClassValidator<targetClass> oValidator= new ClassValidator<targetClass>();
// Here I need to get a reference to the instance of the offending
// SomeBean object whose data has been set to empty...not sure how!
SomeBean oOffendingBean = getTheBadBeanSomehow();
InvalidValue[] badVals = oValidator.getInvalidValues(oOffendingBean);
}
}
So, not only am I choking on what the Spring AOP (pointcut definitions, etc.) configuration would look like to intercept the Hibernate Validator annotations I want, and not only do I not fully grasp how to implement the actual advice (e.g. how to instantiate the offending SomeBean from inside the advice as I mention above in the comments), but I'm not even sure if this solution is possible, Spring or otherwise.
Thanks in advance for some gentle "nudges" in the right direction!
You might be interested in the method validation feature introduced with Hibernate Validator 4.2 which provides support for validating method parameters and return values.
You then might use Seam Validation which integrates this functionality with CDI. If you want to use method validation together with Spring you could have a look this project on GitHub which shows how to integrate the method validation functionality with Spring AOP (disclaimer: I'm the author of this project as well as of Seam Validation).
To make your example working you would have to annote the parameter of the setter method with #NotEmpty like this:
public class SomeBean {
private String data;
#NotEmpty
public String getData() { return data; }
public void setData(#NotEmpty String data) { this.data = data; }
}
I'm using a JPA EntityListener to do some additional audit work and am injecting a Spring-managed AuditService into my AuditEntryListener using #Configurable. The AuditService generates a collection of AuditEntry objects. The AuditService is itself a Singleton scoped bean, and I'd like to gather all the AuditEntry objects under a common key that can then be accessed by the outermost service layer (the one that invoked the persist call which in turn triggered the EntityListener).
I'm looking at using Spring's TransactionSynchronizationManager to set a specific transaction name (using UID() or some other unique strategy) at the beginning of the transaction, and then using that name as a key within the AuditService that will allow me to group all AuditEntry objects created within that transaction.
Is mixing declarative and programmatic transaction management have the potential for trouble? (Though I'm doing nothing more than setting the transaction name). Is there a better way to associate the generated AuditEntry objects with the current transaction? This solution does work for me, but given that the TransactionSynchronizationManager isn't intended for application use, I'd like to make sure that my use of it won't cause some unforseen problems.
Related Question
Finally, a related, but not immediately pertinent question: I know that the documentation for JPA EntityListeners cautions against using the current EntityManager, but if I did want to use it to diff an object against it's persisted self, would I be safe using an #Transactional(propagation=REQUIRES_NEW) annotation around my preUpdate() method?
Prototype Code:
Service Class
#Transactional
public void create(MyEntity e) {
TransactionSynchronizationManager.setCurrentTransactionName(new UID().toString());
this.em.persist(e);
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
#Override
public void afterCommit() {
Set<AuditEntry> entries = auditService.getAuditEntries(TransactionSynchronizationManager.getCurrentTransactionName());
if(entries != null) {
for(AuditEntry entry : entries) {
//do some stuff....
LOG.info(entry.toString());
}
}
}
});
}
JPA EntityListener
#Configurable
public class AuditEntryListener {
#Autowired
private AuditService service;
#PreUpdate
public void preUpdate(Object entity) {
service.auditUpdate(TransactionSynchronizationManager.getCurrentTransactionName(), entity);
}
public void setService(AuditService service) {
this.service = service;
}
public AuditService getService() {
return service;
}
}
AuditService
#Service
public class AuditService {
private Map<String, Set<AuditEntry>> auditEntryMap = new HashMap<String, Set<AuditEntry>>();
public void auditUpdate(String key, Object entity) {
// do some audit work
// add audit entries to map
this.auditEntryMap.get(key).add(ae);
}
}
#Filip
As far as I understand, your requirement is:
Have an unique token generated within each transaction (database
transaction of course)
Keep this unique token easily accessible across all layers
So naturally you're thinking about the TransactionSynchronizationManager provided by Spring as a facility to store the unique token (in this case, an UID)
Be very carefull with this approach, the TransactionSynchronizationManager is the main storage helper to manage all the #Transactional processing for Spring. Under the #Transactional hood, Spring is creating an appropriate EntityManager, an appropriate Synchronization object and attach them to a thread local using TransactionSynchronizationManager.
In your service class code, inside a #Transactional method your are tampering with the Synchronization object, it can end up with undesirable behavior.
I've done an indept analysis of how #Transactional works here, have a look: http://doanduyhai.wordpress.com/2011/11/20/spring-transactional-explained/
Now back to your needs. What you can do is:
Add a Thread local to the AuditService, containing the unique token when entering the #Transactional method and destroy it when exiting the method. Within this method call, you can access the unique token in any layer. Explanation for ThreadLocal usage can be found here: http://doanduyhai.wordpress.com/2011/12/04/threadlocal-explained/
Create a new annotation, let's say #Auditable(uid="AuditScenario1") to annotate methods that need to be audited and use Spring AOP to intercept these method calls and manage the Thread local processing for you
Example:
Modified AuditService
#Service
public class AuditService {
public uidThreadLocal = new ThreadLocal<String>();
...
...
}
Auditable annotation
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
#Documented
public #interface Auditable
{
String uid();
}
Usage of #Auditable annotation
#Auditable(uid="AuditScenario1")
#Transactional
public void myMethod()
{
// Something
}
Spring AOP part
#Around("execution(public * *(..)) && #annotation(auditableAnnotation))
public Object manageAuditToken(ProceedingJoinPoint jp, Auditable auditableAnnotation)
{
...
...
AuditService.uidThreadLocal.set(auditableAnnotation.uid())...
...
}
Hope this will help.
You can come up with a solution using the TransactionSynchronizationManager. We register a "TransactionInterceptorEntityListener" with JPA as an entity-listener. What we wanted to achieve is the ability to listen to CRUD events such that we can work with a spring managed "listener" that has a lifecycle tied to the current transaction (i.e., spring-managed but instance per transaction). We sub-class the JPATransactionManager and introduce in the prepareSynchronization() method, a hook to setup a "TransactionInterceptorSynchronizer." We also use the same hook for allow code (in programmatic tx) to associate and retrieve arbitrary objects with the current transaction and also register jobs that run before/after transaction commit.
The overall code is complex, but definitely do-able. If you use JPATemplates for programmatic tx, it is tough to achieve this. So we rolled our own template that simply calls the JPA template after taking care of the interceptor work. We plan to open-source our JPA library (written on top of Spring's classes) soon.
You can see a pattern of adding custom transactions and hooks with Spring managed transactions in the following library for Postgresql