问题
I am using the current version of Spring Data Rest and Spring Data JPA and have following entity:
public class User {
@Id
@GeneratedValue
private Long id;
private String name;
private String password;
private String email;
...getter/setter methods...
}
I am also using Spring Security
.
My User Repository:
@RepositoryRestResource(
collectionResourceRel = "user",
path = "user",
excerptProjection = UserSimpleProjection.class)
public interface UserRepository extends PagingAndSortingRepository<User, Long> {
}
For Example:
- User 1 is logged in
- User 1 requests
http://localhost:8080/user/1
- all fields are visible - User 1 requests
http://localhost:8080/user/2
- justid
andname
are visible.
I tried different solutions with Jackson, none of them solved my problem:
- Use of JsonView: I found no way, to change the view for the
ObjectMapper
depending on the logged in User - Implemented different Jackson Filters as described here with the same issue that I found no way to change the
ObjectMapper
config for the different requests.
Then I found Projections.
I created a projection:
@Projection(name = "simple", types = User.class)
public interface UserSimpleProjection {
public Long getId();
public String getName();
}
and another detailed one:
@Projection(name = "detailed", types = User.class)
public interface UserDetailProjection extends UserSimpleProjection{
public String getEmail();
}
So far so good, I get different results depending on my request.
Is there a way to automatically switch the projection depending on Spring Security and/or limit different Projections for different roles?
回答1:
You can add a "virtual" value property into the projection that invoke a service method with security checks:
@Projection(name = "detailed", types = User.class)
public interface UserDetailProjection extends UserSimpleProjection{
@Value("#{@userService.checkAccess(target)? target.email : null}")
public String getEmail();
}
Where your custom UserService
component would return true
if email should be exposed or simply has @PreAuthorize
on checkAccess(..)
to throw an AccessDeniedException
whatever is better for you.
Note, the target
property in the SpEL holds the original object - provided by Spring-DATA.
回答2:
You can also do it using a RegexRequestMatcher in your Spring Security config like this:
.regexMatchers(HttpMethod.GET,"/user/.*projection=simple.*").hasRole("ROLE_ADMIN")
回答3:
No, Spring Data REST projections don't support this.
来源:https://stackoverflow.com/questions/28794145/spring-data-rest-security-based-projection