java 拒绝所有URL,除非通过注解启用

ajsxfq5m  于 2023-10-14  发布在  Java
关注(0)|答案(1)|浏览(95)

我想拒绝Sping Boot 应用程序中的所有请求,除非它们的方法级别注解被满足。

@Bean
public SecurityFilterChain configure(final HttpSecurity http) throws Exception {
    return http.cors(withDefaults())
            .csrf(AbstractHttpConfigurer::disable)
            .authorizeHttpRequests()
            .antMatchers("/login").permitAll()
            .anyRequest().denyAll()
            .and()
            .sessionManagement((session) -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .addFilterBefore(bamRequestFilter, UsernamePasswordAuthenticationFilter.class)
            .build();
}

@PutMapping(path = "/getInfo")
@PreAuthorize("hasAnyAuthority('GET')")
public ActionResult getInfo(@RequestBody Map<String, String> input) {
    return service.getInfo(input);
}

这实际上拒绝了正确的用户。当我将.anyRequest().denyAll()更改为.anyRequest().authenticated()时,此控制器可以工作,但允许其他控制器。我希望所有的开发人员都能在各个方法上显式地配置安全性。

ct3nt3jp

ct3nt3jp1#

据我所知,这不容易用Spring Security检查,并且可能需要一些(丑陋的)反射(可以在this article中看到)。
另一种方法是用ArchUnit编写一个单元测试。ArchUnit有一个干净的(更干净的)API,并且有一个好处,你可以在测试阶段运行它,而不是必须先运行或部署你的应用程序,然后依靠最终用户注意到一些禁止的错误。
这样的测试看起来像这样:

@Test
void ensureEachControllerHasPreAuthorize() {
    JavaClasses importedClasses = new ClassFileImporter().importPackages("com.example.demo");
    ArchRule rule = methods().that()
        .areMetaAnnotatedWith(RequestMapping.class)
        .and().areDeclaredInClassesThat().areMetaAnnotatedWith(Controller.class)
        .should().beAnnotatedWith(PreAuthorize.class)
        .orShould().beDeclaredInClassesThat().areAnnotatedWith(PreAuthorize.class);
    rule.check(importedClasses);
}

一些评论:

  • areMetaAnnotatedWith(RequestMapping.class)包括@RequestMapping@GetMapping@PostMapping等变体。.
  • 同样适用于areMetaAnnotatedWith(Controller.class),包括@Controller@RestController
  • 我允许用@PreAuthorize注解控制器方法和类。如果只想在@PreAuthorize应用于方法级别而不是类级别时通过测试,那么可以删除以orShould()开头的行。
  • 默认情况下,ArchUnit不包含在任何Sping Boot 启动器中。你必须自己包括依赖关系。

相关问题