Spring 数据休息 + Spring 安全:@Secured 不工作

Spring Data Rest + Spring Security: @Secured not working

我正在使用 Spring Data RestSpring BootSpring Security 构建应用程序。我需要在方法上使用 @Secured 注释,并且我按以下方式配置了 Spring Security

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    // @formatter:off
    @Override
    protected void configure(final HttpSecurity http) throws Exception {
        http
                .securityContext().securityContextRepository(securityContextRepository())
                    .and()
                .exceptionHandling()
                .accessDeniedPage(RestPath.Errors.ROOT + RestPath.Errors.FORBIDDEN)
                    .and()
                .csrf().disable();
    }
    // @formatter:on

    @Bean
    public SecurityContextRepository securityContextRepository() {
        return new ApiUserSecurityContextRepository();
    }

    @Bean
    public UserDetailsService userDetailsService() {
        return new ApiUserDetailsService();
    }

    @Bean
    public AuthenticationManager authenticationManager() throws Exception {
        return new ProviderManager(Collections.singletonList(authenticationProvider()));
    }

    @Bean
    public AuthenticationProvider authenticationProvider() throws Exception {
        final DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
        authenticationProvider.setUserDetailsService(userDetailsService());
        authenticationProvider.setPasswordEncoder(passwordEncoder());
        return authenticationProvider;
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

这种类型的配置适用于常规 MVC 控制器和 returns 403 当我尝试访问它们时。例如,以下控制器安全有效:

@ResponseBody
@RequestMapping(value = RestPath.Configs.SLASH_TEST, method = RequestMethod.GET, produces = MediaTypes.HAL_JSON_VALUE)
@Secured({"ROLE_USER"})
public ResponseEntity test(@RequestParam(value = RestParam.DB_TEST, required = false) final boolean dbTest) throws ApplicationAvailabilityException {
    final AppTestData appTestData = configService.testAppAvailability(dbTest);
    return ResponseEntity.ok(projectionFactory.createProjection(AppTestProjection.class, appTestData));
}

但是,当我尝试在 rest 存储库上使用 @Secured 注释时 - 它不会,例如:

@RepositoryRestResource(collectionResourceRel = Shop.COLLECTION_NAME, path = RestResourceRel.SHOPS, excerptProjection = StandardShopProjection.class)
@Secured({"ROLE_USER"})
public interface RestShopRepository extends MongoRepository<Shop, String> {

    @Secured({"ROLE_ADMIN"})
    @Override
    Shop findOne(String s);
}

ApiUserSecurityContextRepository 正在为这两种方法调用,但只有自定义 MVC 控制器到达链的末尾,我可以检查它是否访问 vote() 中的方法 RoleVoter class 用于授予访问权限。 例如,我检查了 Spring Data Rest + Spring Security 示例,因此 @Secured@PreAuthorize 注释应该与 Spring Data Rest 一起使用。知道为什么它们不起作用吗?

问题终于解决了。问题出在下面,我在不同的应用程序模块中有另一个 ShopRepository,它没有用 @RepositoryRestResource 注释,它是使用 REST 访问它时使用的那个。

自定义中的以下配置行 RepositoryRestConfigurerAdapter 修复了需要公开的存储库的探索,因此现在只公开注释的:

config.setRepositoryDetectionStrategy(RepositoryDetectionStrategy.RepositoryDetectionStrategies.ANNOTATED);

在那之后我根本无法使用 REST 访问该资源,所以我发现它对 Spring 不可见。我只需要在 API 级别启用 Mongo 存储库,注释 @EnableMongoRepositories.