Chen Li (Migrated from SEC-3212) said:
I was trying to authorize apis work with Spring Data JPA. When I try to authorize permission for getting page of entities, it throws the exception: java.lang.IllegalArgumentException: Filter target must be a collection or array type, but was Page 0 of 3 containing domain.Consumption instances
The code is:
@PreAuthorize(
"hasRole('ROLE_USER')")
@PostFilter(
"hasPermission(filterObject, 'read') or " +
"hasPermission(filterObject, admin)")
Page<Consumption> getAllConsumptions(Pageable pageable);
Will Spring Security filter those are not a collection nor array like 'org.springframework.data.domain.Page' above?
Comment From: spring-projects-issues
Rob Winch said:
Thanks for the report! It is unlikely Spring Security will ever support @PostFilter on Page objects. This is because the result won't be valid anymore (i.e. you request 10 results, Spring Security will remove 2 of them and you will only have 8). Instead, you should use the Spring Data integration to update your query. See http://docs.spring.io/spring-security/site/docs/4.0.x/reference/htmlsingle/#data
Comment From: spring-projects-issues
Chen Li said:
@Rob You are right. Thank you :)
Comment From: rwong2000
@rwinch
I am having trouble replacing the @PostFilter with @Query and hasPermission.
Is there an example for this type of query ?
Something along the lines of
@Query("select e from MyEntity e where 1= ?#{hasPermission(e.id,'com.foo.MyEntity', 'read') } ")
Page<MyEntity> findEntities(Pageable pageable);
Comment From: jorgeliano-lcg
@rwong2000 Did you ever get an example for this? I'm trying to do the same thing
Comment From: ghost
@jorgeliano-lcg & @rwong2000 did you guys find any solution to ?
@Query("select e from MyEntity e where 1= ?#{hasPermission(e.id,'com.foo.MyEntity', 'read') } ") Page<MyEntity> findEntities(Pageable pageable);
Comment From: sac-cas
Maybe not the right place, but how you manage such a query on a no sql db like mongo?
Actually we got:
@Query("{organization: ?#{ hasRole('ROLE_MANAGER') ? {$exists:true} : principal.organizationId}}")
Page<Briefing> findAll(Pageable pageable);
So if the user has the role manager he will get all entities otherwise only the one of his organization. I prefer using hasPermission instead of hasRole. Any idea?
Comment From: shamal
Refering to:
Rob Winch said:
Thanks for the report! It is unlikely Spring Security will ever support @PostFilter on Page objects. This is because the result won't be valid anymore (i.e. you request 10 results, Spring Security will remove 2 of them and you will only have 8). Instead, you should use the Spring Data integration to update your query. See http://docs.spring.io/spring-security/site/docs/4.0.x/reference/htmlsingle/#data
With the following code:
public interface BookRepository extends JpaRepository<Book, Long> {
@PreAuthorize("hasAuthority('AUTHOR')")
@Query("select b from Book b where b.author.id = ?#{ principal?.id }")
Page<Facility> findAllOwned(Pageable p);
}
I'm getting the below error:
org.springframework.expression.spel.SpelEvaluationException:
EL1008E:
Property or field 'id' cannot be found on object of type 'java.lang.String' - maybe not public?
The full issue is in Stackoverflow https://stackoverflow.com/questions/48478982/spelevaluationexception-when-using-spring-security-expressions-with-query
Comment From: j3ernhard
I'm also working with Spring Data and Spring Security ACL and I have the same problem as @rwong2000 , @jorgeliano-lcg and @saubhagyab . Is there any working solution for that, I did not find anything on stackoverflow or elsewhere. I have debugged it and it searches with e.id on Page or Pageable instead of MyEntity.
Comment From: sebboursier
Same as @rwong2000, trying to access to a SPQL parameter in a SpEL expression that is itself in the SPQL.
@Query("select o from #{#entityName} o where 1 = ?#{@someBean.some(o, authentication)} ")
Page<T> findAll(Pageable pageable);
But can't figure how to access 'o' in SpEL.
Comment From: selvaebi
Has anybody have any solution for this ? else any workaround for applying security over Page returning repository methods ? i can do a default implementation and apply security over it , but still checking is there any solution for this.
Comment From: RhysWilliams-CSI
Same as @rwong2000, trying to access to a SPQL parameter in a SpEL expression that is itself in the SPQL.
@Query("select o from #{#entityName} o where 1 = ?#{@someBean.some(o, authentication)} ") Page<T> findAll(Pageable pageable);But can't figure how to access 'o' in SpEL.
Did you ever figure this bit out? Running into same issue.
Comment From: mikezerosix
Using @Query to solve problem in @PostFilter is not a solution, it is barely a temp workaround. That in unmaintainable spaghetti. Hardcododing S(P)QL code into your application is NOT a good solution.
Reopen this !
Comment From: epernice
For some use cases the @Query workaround seems like it would not work. For example, JpaSpecificationExecutor has this:
Page<T> findAll(Specification<T> spec, Pageable pageable);
Our codebase is using this heavily. I'm not sure how you would write a custom @Query that filters based on the provided spec and I suspect it is not feasible.