【问题标题】:Spring 4 Rest @Query annotation not working with security PrincipalSpring 4 Rest @Query 注释不适用于安全主体
【发布时间】:2018-01-24 00:49:51
【问题描述】:

我有一个简单的(此时仍然是演示程序)Spring 程序(Spring Rest 和 Security),它以简单的方式工作。通过 JpaRepository,我可以获取所有(/option 由 findAll() 处理)、GET 一个(/option/1 由 findOne(Long id) 处理)、PUT 和 POST。

我的业务模型表明,登录用户应该只能看到他们有权访问的记录。所以 findAll() 应该返回三个记录, findOne(id) 应该返回一个或零。

我相信我必须将它们与注释中的 Principal 对象联系起来。我尝试了各种方案,但还没有弄清楚 Spring 想要我什么。对于 findAll() 我试过这个:

@Override
@Query("from Option o where o.id = 11")
public List<Option> findAll();

但是,findAll() 仍然返回许多记录。

然后我尝试将我的查询与校长联系起来:

@Override
@Query("from Option o where o.id = ?#{ principal.id}")
public List<Option> findAll(); 

(我也试过?#{#principal.id})

这以有趣的方式失败了。

  • 当它返回 HTTP 500 时,我被告知找不到“主体”。
  • 一旦我重新配置我的程序,我得到一个 HTTP 404,这意味着我问错了什么。但由于我不知道如何转储 principal.id 值(从接口记录?)我看不出我做错了什么。

这是我公开 UserDetailsS​​ervice 的方式:

@Service
public class JwtUserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

这是我在 pom.xml 中配置主体的方式:

    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-data</artifactId>
        <!-- <version>4.2.1.RELEASE</version> -->
    </dependency>

在 Java 中:

@SuppressWarnings("SpringJavaAutowiringInspection")
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private JwtAuthenticationEntryPoint unauthorizedHandler;

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    public void configureAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
        authenticationManagerBuilder
                .userDetailsService(this.userDetailsService)
                .passwordEncoder(passwordEncoder());
    }

我的问题是:

  • 为什么@Query("from Option o where o.id = 11") 不只返回一条记录?
  • 如何判断“principal”的属性,从而判断它的ID是不是我想的那样?
  • 我还应该问其他问题吗?

谢谢, 杰罗姆。

【问题讨论】:

    标签: spring-security spring-data-jpa spring-el


    【解决方案1】:

    为什么@Query("from Option o where o.id = 11") 不只返回一条记录?

    因为这不是一个有效的 JPQL 查询。您的硬编码测试查询必须是 @Query("SELECT o FROM Option o WHERE o.id = 11")

    如何判断“principal”的属性,从而判断它的ID是不是我想的那样?

    您必须为查询启用 Spring Security SpEL 功能。

    @Configuration
    @EnableJpaRepositories
    class SecurityConfiguration {
    
        @Bean
        EvaluationContextExtension securityExtension() {
            return new SecurityEvaluationContextExtension();
        }
    }
    

    解释了here

    现在?#{principal.id} 可以工作,如果您有一个自定义的UserDetails-Implementation 和id-字段。例如:

    import org.springframework.security.core.userdetails.User;
    
    public class HapaUserDetails extends User { //User implements UserDetails
    
        private final long id;
    
        //constructor and getters
    }
    

    【讨论】:

    • 我添加了 SecurityEvaluationContextExtension 位。我的 GET one (/option/1) 现在正在与校长合作!也感谢您向我展示我使用的是 HQL,而不是 SQL。这样问题2就解决了。但是,我的 GET many 仍然无法正常工作:@Query("select o from Option o where o.id = ?#{principal.id}") 返回很多行,... where o.id = 11.
    • 这是 JPQL 而不是 SQL。数据库中的option-entities 可能有问题。检查他们是否真的有不同的 id。
    • 在我的应用程序中,Option.id 字段被注释为 (at)Id 和 (at)Column(name="id")。 Option 类使用 (at)Entity 和 (at)Table(name="choice") 进行注释。在 MySQL 中,选择表具有“id”(int)作为 auto_increment,具有 PRIMARY KEY 索引。是的,数据库使用与 Java 类不同的表名。 (Stackoverflow 对我使用“at”符号有问题,因此进行了替换。)
    • auto_increment 真的有用吗?你说“返回很多行”。为什么不看行中的内容(在本例中是每行的 id)?我在我的环境中使用类似的查询并且没有问题。您是否尝试使用@GeneratedValue 注释id 字段?您是否在 UserDetailsService 实现中设置了正确的 id
    • 自动增量正在工作。我有一个来自测试网页的 POST,每次我发送一个 POST /option 时,MySQL 客户端表都会获得一条带有新 ID 值的新记录。我在 findAll() 上设置了一个令人发指的@Query,但仍然取回了所有行。 Spring 目前忽略了我在 findAll() 上的注释。
    猜你喜欢
    • 2016-11-17
    • 2016-08-27
    • 2011-05-16
    • 1970-01-01
    • 2021-11-15
    • 2014-08-31
    • 2016-05-01
    • 2015-09-25
    • 2019-08-13
    相关资源
    最近更新 更多