Spring Security Sping Boot 3迁移后PreAuthorize注解不起作用

dbf7pr2w  于 2023-06-29  发布在  Spring
关注(0)|答案(1)|浏览(234)

我们正在尝试将我们的应用程序从Java 8 + Sping Boot 2迁移到Java 17 + Spring Boot 3。几乎所有的事情都与我们用@PreAuthorize注解的API调用分开工作。
下面是我们配置的简化版本:

@Configuration
@RequiredArgsConstructor
@EnableWebSecurity(debug = true)
@EnableMethodSecurity
public class SecurityConfiguration {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);

        http.csrf().disable();
        http.cors();
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        http.authorizeHttpRequests()
            .requestMatchers("/api/**")
            .authenticated()
            .and()
            .oauth2ResourceServer()
            .jwt()
            .jwtAuthenticationConverter( new JwtAuthenticationConverter() );

        return http.build();
    }

    @Bean
    public JwtDecoder jwtDecoder(OAuth2ResourceServerProperties properties) {
        NimbusJwtDecoder jwtDecoder = NimbusJwtDecoder.withJwkSetUri(
                properties.getJwt().getJwkSetUri()).build();

        return jwtDecoder;
    }
}

class JwtAuthenticationConverter implements Converter<Jwt, AbstractAuthenticationToken> {

    @Override
    public AbstractAuthenticationToken convert(Jwt jwt) {
        return new JwtAuthenticationToken(jwt, new JwtAuthoritiesConverter().convert(jwt));
    }
    
}

class JwtAuthoritiesConverter implements Converter<Jwt, Collection<GrantedAuthority>> {

    @Override
    public Collection<GrantedAuthority> convert(Jwt jwt) {
        Collection<GrantedAuthority> grantedAuthorities = new ArrayList<GrantedAuthority>();
        grantedAuthorities.add(new SimpleGrantedAuthority("SOME_AUTHORITY"));

        return grantedAuthorities;
    }

}

还有一个示例方法:

@PreAuthorize("hasAnyAuthority('SOME_AUTHORITY')")
    @GetMapping("/someObjects") APIResponse<SomeObject> testMethod(JwtAuthenticationToken principal){
        
        List<GrantedAuthority> principalAuthorities= principal.getAuthorities().stream().collect(Collectors.toList());
        log.info("Authorities: " + principalAuthorities.toString());
        
        List<GrantedAuthority> authorities = SecurityContextHolder.getContext().getAuthentication().getAuthorities().stream().collect(Collectors.toList());
        log.info("Security Context" + authorities.toString());
        
        return APIResponse.singleton(new SomeObject());
    }

取出PreAuthorize注解允许我们访问该方法并打印GrantedAuthorizations,这似乎是正确的:
2023-06-28T09:48:27,618 INFO SomeController::testMethod(223):当局:[SOME_AUTHORITY] 2023-06-28T09:48:27,618 INFO SomeController:安全上下文[SOME_AUTHORITY]
然而,将其添加回会导致返回HTTP 401。当启用trace时,我们还会看到这些日志:
2023-06-28T11:27:13,166 DEBUG o.s.o.s.r.w.a. BearerTokenAuthenticationFilter::doFilterInternal(143):将SecurityContextHolder设置为JwtAuthenticationToken [Principal=org.springframework.security.oauth2.jwt.Jwt@eb761cc7,Credentials=[PROTECTTED],Authenticated=true,Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1,SessionId=null],授予的权限=[SOME_AUTHORITY]]
...
2023-06-28T11:27:13,174 TRACE o.s.s.w.a.ExceptionTranslationFilter::handleAuthenticationException(184):由于身份验证失败,发送到身份验证入口点org.springframework.security.authentication.AuthenticationCredentialsNotFoundException:在SecurityContext中找不到身份验证对象
我们能查到什么进一步追查吗?同样的代码在我们的旧代码库中运行得很好(使用WebSecurityConfigureAdapter)。
编辑:如果我们设置了以下内容,则“预授权”似乎适用于我们:

SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_THREADLOCAL);

而不是:

SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);

任何解释都将非常感谢。

rhfm7lfc

rhfm7lfc1#

在配置文件中添加以下注解:

@EnableGlobalMethodSecurity(prePostEnabled = true)

相关问题