Spring 4 Rest @Query 注释不适用于安全主体
Spring 4 Rest @Query annotation not working with security Principal
我有一个简单的(此时仍然是演示程序)Spring 程序(Spring 休息和安全),它以简单的方式工作。通过 JpaRepository,我可以获取所有(/选项由 findAll() 处理)、获取一个(/option/1 由 findOne(Long id) 处理)、PUT 和 POST.
我的业务模型规定登录用户只能看到他们有权访问的记录。所以一个 findAll() 应该 return 可能是三个记录,一个 findOne(id) 应该 return 一个或零。
我认为我必须将它们与注释中的 Principal 对象联系起来。我已经尝试了多种方案,但还没有想出 Spring 想要我做什么。对于 findAll() 我试过这个:
@Override
@Query("from Option o where o.id = 11")
public List<Option> findAll();
但是,findAll() 仍然有 return 条记录。
然后我尝试将我的查询与委托人联系起来:
@Override
@Query("from Option o where o.id = ?#{ principal.id}")
public List<Option> findAll();
(我也试过了?#{#principal.id})
这以有趣的方式失败了。
- 当它 return 出现 HTTP 500 时,我被告知无法找到 "principal"。
- 重新配置我的程序后,我收到 HTTP 404,这意味着我的问题有误。但是因为我不知道如何转储 principal.id 值(从界面记录?)我看不出我做错了什么。
以下是我公开 UserDetailsService 的方式:
@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") return 不是只有一条记录?
- 如何判断 "principal" 的属性,以便判断它的 ID 是否是我认为的那样?
- 我还应该问其他问题吗?
谢谢,
杰罗姆
Why doesn't the @Query("from Option o where o.id = 11") return only one record?
因为这不是有效的 JPQL 查询。您的硬编码测试查询必须是 @Query("SELECT o FROM Option o WHERE o.id = 11")
How can I tell the attributes of "principal", so I can tell if its ID is what I think it is?
您必须为查询启用 Spring 安全 SpEL 函数。
@Configuration
@EnableJpaRepositories
class SecurityConfiguration {
@Bean
EvaluationContextExtension securityExtension() {
return new SecurityEvaluationContextExtension();
}
}
已解释 here。
现在 ?#{principal.id}
可以工作了,如果你有一个自定义 UserDetails
- 实现和 id
- 字段。例如:
import org.springframework.security.core.userdetails.User;
public class HapaUserDetails extends User { //User implements UserDetails
private final long id;
//constructor and getters
}
我有一个简单的(此时仍然是演示程序)Spring 程序(Spring 休息和安全),它以简单的方式工作。通过 JpaRepository,我可以获取所有(/选项由 findAll() 处理)、获取一个(/option/1 由 findOne(Long id) 处理)、PUT 和 POST.
我的业务模型规定登录用户只能看到他们有权访问的记录。所以一个 findAll() 应该 return 可能是三个记录,一个 findOne(id) 应该 return 一个或零。
我认为我必须将它们与注释中的 Principal 对象联系起来。我已经尝试了多种方案,但还没有想出 Spring 想要我做什么。对于 findAll() 我试过这个:
@Override
@Query("from Option o where o.id = 11")
public List<Option> findAll();
但是,findAll() 仍然有 return 条记录。
然后我尝试将我的查询与委托人联系起来:
@Override
@Query("from Option o where o.id = ?#{ principal.id}")
public List<Option> findAll();
(我也试过了?#{#principal.id})
这以有趣的方式失败了。
- 当它 return 出现 HTTP 500 时,我被告知无法找到 "principal"。
- 重新配置我的程序后,我收到 HTTP 404,这意味着我的问题有误。但是因为我不知道如何转储 principal.id 值(从界面记录?)我看不出我做错了什么。
以下是我公开 UserDetailsService 的方式:
@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") return 不是只有一条记录?
- 如何判断 "principal" 的属性,以便判断它的 ID 是否是我认为的那样?
- 我还应该问其他问题吗?
谢谢, 杰罗姆
Why doesn't the @Query("from Option o where o.id = 11") return only one record?
因为这不是有效的 JPQL 查询。您的硬编码测试查询必须是 @Query("SELECT o FROM Option o WHERE o.id = 11")
How can I tell the attributes of "principal", so I can tell if its ID is what I think it is?
您必须为查询启用 Spring 安全 SpEL 函数。
@Configuration
@EnableJpaRepositories
class SecurityConfiguration {
@Bean
EvaluationContextExtension securityExtension() {
return new SecurityEvaluationContextExtension();
}
}
已解释 here。
现在 ?#{principal.id}
可以工作了,如果你有一个自定义 UserDetails
- 实现和 id
- 字段。例如:
import org.springframework.security.core.userdetails.User;
public class HapaUserDetails extends User { //User implements UserDetails
private final long id;
//constructor and getters
}