spring-projects / spring-projects/spring-security
SEC-2502: Overriding @PreAuthorize annotations on sub-interfaces does not behave as expected.
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 9.6k
- Forks
- 6.3k
- Avg merge
- 2d 11h
- Merged PRs (30d)
- 52
Description
Franklin Bristow (Migrated from SEC-2502) said:
I have a class hierarchy that includes a generic service implementation that all other service implementations extend. The generic service implementation has a corresponding generic service interface, and each of the other service implementations have corresponding interfaces that extend the generic interface. For example:
public interface GenericService<KeyType, ValueType> {
// in general, anyone that's logged in should be able to read stuff.
@PreAuthorize("isAuthenticated()")
public ValueType read(KeyType s);
}
public class GenericServiceImpl<KeyType, ValueType> implements GenericService<KeyType, ValueType> {
public ValueType read(KeyType s) {
// implementation of read
}
}
public interface WidgetService extends GenericService<Long, Widget> {
// only administrators can read widgets:
@PreAuthorize("hasRole('ROLE_ADMIN')")
public Widget read(Long s);
}
public class WidgetServiceImpl extends GenericServiceImpl<Long, Widget> implements WidgetService {
// GenericServiceImpl provides a default implementation of read.
}
What I expect to happen is that the @PreAuthorize annotation on the sub-interface will override the @PreAuthorize annotation on the super-interface.
The behavior of @PreAuthorize that I am receiving depends on the type of proxying that I am using (JDK-based vs Cglib-based).
By descending into the proxy with the debugger in eclipse, I can see that the instance of the method that the proxy is finding changes, depending on the type used on the reference of the injected class (i.e., using GenericService<Long, Widget> service vs WidgetService service).
I've attached a minimal test case that covers the problem that I am describing with three test cases that show what I expect to happen, with some comments that explain how changing the type of proxy used causes one, or the other to fail. One test case fails in all configurations.
I understand that I may be running into a language-level problem with Java and type erasure, but I think that what I'm trying to accomplish is not entirely unreasonable.
I think that this is related to two other issues: SEC-1234 and SEC-2144.
If the problem that I'm describing is a language-level problem, are there any other approaches that I can use to accomplish my expectations?
Thank you for developing Spring Security, it's saved me plenty of time, and the documentation is top-notch.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the attached minimal test case and its three tests, then inspect how @PreAuthorize metadata is resolved for JDK-based and Cglib-based proxies. Compare the behavior when the service is referenced through GenericService versus WidgetService; done means the sub-interface annotation behaves consistently with the stated expectations, or the limitation and supported approach are documented.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, spring
- Domain
- authorization, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100