Reputation: 2481
I'm trying to create a generic controller using spring mvc 3.2.3 and spring security 3.1.3. What i'm trying to achieve is something like this:
public abstract class DataController<E extends PersistentEntity> {
protected abstract E getEntity(String id);
@RequestMapping(value="/view/{id}", method=RequestMethod.GET)
public String view(@PathVariable("id") String id, ModelMap map) {
E ent = getEntity(id);
map.put("entity", entity);
return "showEntity";
}
}
My extended class will have a specific controller mapping in the class name so that i can access the url by using the controller name:
@Controller
@RequestMapping("/company**")
@Secured("ROLE_ADMIN")
public class CompaniesController extends DataController<Company> {
@Autowired
private AppService appService;
@Override
protected Company getEntity(String id) {
return appService.getCompany(id);
}
}
My problem is that the url /company/view is not secured by ROLE_ADMIN and can be accessed by anyone, (i think) because the /view is not defined in the controller where the @Secured is being used.
This can be fixed by just overriding the view method and define the mapping in my company class:
. . .
@Override
@RequestMapping(value = "/view/{id}", method = RequestMethod.GET)
public String view(String id, ModelMap map) {
return super.view(id, map);
}
. . .
In this case the security works correctly, but i want to know if there is another method. Since i have a lot of methods in my abstract class, this will create a problem and a mess to override all methods just to call the super.
Is there a way to fix this issue?
thanks all for the help :)
Upvotes: 3
Views: 2534
Reputation: 4065
I know it's a year later, but I had the same problem and figured out a possible solution for this. It is not 100% annotation based, but works and is somewhat elegant
The abstract superclass:
@PreAuthorize("hasAnyRole(this.roles)")
public abstract class DataController<E extends PersistentEntity>
{
protected abstract E getEntity(String id);
protected abstract String[] getRoles();
@RequestMapping(value="/view/{id}", method=RequestMethod.GET)
public String view(@PathVariable("id") String id, ModelMap map) {
E ent = getEntity(id);
map.put("entity", entity);
return "showEntity";
}
}
On the subclass you simply implement getRoles()
to return an array of roles that are required to access this class.
@PreAuthorize
is another way to check authentication, that allows you to use SpEL expression. this.roles
refers to he getRoles()
property on the annotated object.
Upvotes: 8