【问题标题】:Spring Using SpEL PrincipalSpring 使用 SpEL 主体
【发布时间】: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 对象字段@参见AuthorizationServerConfigurerAdapterWebSecurityConfiguration 部分

标签: java spring hibernate spring-mvc


【解决方案1】:

在网站示例 (https://spring.io/blog/2014/07/15/spel-support-in-spring-data-jpa-query-definitions) 中,他们指定您可以使用 ?#{principal.id} 并且在执行上面的代码时确实会调用它,但由于某种原因它在 @Query 绑定上失败。 但是我尝试用另一个示例案例运行它

@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 = ?#{#security.principal.id} ")

这奏效了。 我在这里找到了另一个例子: https://github.com/spring-projects/spring-data-examples/blob/master/jpa/security/src/main/java/example/springdata/jpa/security/SecureBusinessObjectRepository.java

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2017-03-10
  • 1970-01-01
  • 2019-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多