【发布时间】:2017-08-27 01:34:35
【问题描述】:
我正在尝试使用本文档中的 SpEL https://spring.io/blog/2014/07/15/spel-support-in-spring-data-jpa-query-definitions 通过 ?#{principal.id}
做一个查询过滤结果问题是Spring返回异常
org.hibernate.QueryException:并非所有命名参数都已设置: [1] [select p , p.store, p.category from Product p JOIN p.store s 加入 p.category c WHERE p.store.id = :id AND p.keywords LIKE :keyword 和 p.store.ownerId = ?1 ];嵌套异常是 java.lang.IllegalArgumentException:org.hibernate.QueryException:不是 所有命名参数均已设置:[1] [select p , p.store, p.category from Product p JOIN p.store s JOIN p.category c WHERE p.store.id = :id AND p.keywords LIKE :keyword AND p.store.ownerId = ?1 ]
我已经设置了以下代码,它正在执行中。
@Service
public class SecurityEvaluationContextExtension extends EvaluationContextExtensionSupport {
@Override
public String getExtensionId() {
return "security";
}
@Override
public SecurityExpressionRoot getRootObject() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
System.out.println("SER >>>>> " + authentication.getPrincipal().toString() + " -- " );
return new SecurityExpressionRoot(authentication) {};
}
}
@Configuration
@EnableJpaRepositories
public class SecurityConfiguration {
@Bean
EvaluationContextExtension securityExtension() {
return new SecurityEvaluationContextExtension();
}
}
我正在使用这个服务器,它有一个 Spring 资源服务器,因此使用下面的翻译从授权服务器获取 Id。我确认代码执行和翻译良好,但出现上述异常。
@Service
public class myPrincipalExtractor implements PrincipalExtractor {
@Override
public UserInfo extractPrincipal(Map<String, Object> map) {
Map<String,Object> principal = null;
if (map.containsKey("principal")) {
principal = (Map<String, Object>) map.get("principal");
}
UserInfo user = new UserInfo();
if (principal != null ) {
if (principal.containsKey("id")) {
user.setId(Long.parseLong(principal.get("id").toString()));
}
if (principal.containsKey("username")) {
user.setUsername(principal.get("username").toString());
}
if (principal.containsKey("email")) {
user.setEmail(principal.get("email").toString());
}
}
System.out.println("----> " + user.getUsername() + " -> " + user.getId());
return user;
}
}
查询是...
@CrossOrigin
public interface StoreRepository extends CrudRepository<Store, Long>
{
@Query("select p , p.store, p.category from Product p JOIN p.store s " +
" JOIN p.category c " +
" WHERE p.store.id = :id AND p.keywords LIKE %:keyword% AND p.store.ownerId = ?#{principal.id} ")
List<Product> findByKeywordIgnoreCase(@Param("id") Long id , @Param("keyword") String keyword);
}
更多信息:
我在 SecurityExpressionRoot 中执行了下面的代码,所以现在我知道当我放置 SpEL 并且 ID 和用户名存在于对象中时,它确实被调用了。还尝试将返回的对象强制转换为 Principal 并发生了同样的问题。
AND p.store.ownerId = ?#{principal.id}
return new SecurityExpressionRoot(authentication) {
@Override
public UserInfo getPrincipal() {
System.out.println("Fetching the principal has user " + authentication.getPrincipal().toString());
return (UserInfo) authentication.getPrincipal();
}
};
【问题讨论】:
-
我在一个示例项目中使用了类似的拼写,你可以在 github 上看到它,但在我的例子中,我没有使用
PincipalExtractor,在这个例子中我使用的是UserDetailService为了使用自定义 id 字段检索主体:github.com/faustocdiaz/spring-security-spel-sample -
我正在使用从授权服务器获取信息的 OAuth2 ResourceServer。鉴于您的解决方案,我需要构建一个 restTemplate 客户端?
-
您好 Fernando,我认为这个示例结合了 oauth2 和 UserDetailService 这两种方法,以便用您需要注入
@Query注释 @987654323 的值填充principal对象字段@参见AuthorizationServerConfigurerAdapter和WebSecurityConfiguration部分
标签: java spring hibernate spring-mvc